summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjkar8572 <jkar8572>2004-01-05 09:34:42 +0000
committerjkar8572 <jkar8572>2004-01-05 09:34:42 +0000
commit07c4d96601d69b589321316a2c46cc839d2448b2 (patch)
treecb07ac47bce6cfe8cc32ffb1ff8ccac386db2641
parentac836075998abb743c0f53f66d45db2d504f5485 (diff)
warnquota(8) supports getting of e-mail address via LDAP (James Bourne)
warnquota(8) supports checking whether user is not over quota on mail partition (James Bourne) fixed typo in quotacheck.8 (Noel Koethe)
-rw-r--r--Changelog4
-rw-r--r--Makefile.in2
-rw-r--r--configure.in10
-rw-r--r--quotacheck.82
-rw-r--r--quotacheck.c3
-rw-r--r--warnquota.c230
-rw-r--r--warnquota.conf27
7 files changed, 256 insertions, 22 deletions
diff --git a/Changelog b/Changelog
index 9b83e4f..0180087 100644
--- a/Changelog
+++ b/Changelog
@@ -4,6 +4,10 @@ Changes in quota-tools form 3.10 to 3.11
* added #include <paths.h> in quotasys.c to avoid compile problems on some systems (Jan Kara)
* changed detection of filesystem to be able to parse comma separated list (Jan Kara)
* fixed bug in quotacheck(8) which counted wrongly files larger than 2GB (Posta Zoltan)
+* fixed compile problem with quotacheck and new kernels (Michael Meskes, Jan Kara)
+* fixed typo in quotacheck manpage (Noel Koethe)
+* warnquota(8) can get mail addresses via LDAP (James Bourne)
+* warnquota(8) can avoid sending e-mail when user is over quota on mail partition (James Bourne)
Changes in quota-tools from 3.09 to 3.10
* alternative port can be specified to rpc.rquotad by -p option (Jan Kara)
diff --git a/Makefile.in b/Makefile.in
index 301406b..e084dc6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -6,6 +6,7 @@ EXT2LIBS = @EXT2LIBS@
RPCSRC = rquota.h rquota_xdr.c rquota_clnt.c
LIBS = @LIBS@
LDFLAGS = @LDFLAGS@
+LDAPLIBS = @LDAPLIBS@
# Add lines to /etc/hosts.allow and /etc/hosts.deny
# like: "rquotad: ALL@ALL except my.host.i.want.com" in hosts.deny means
@@ -112,6 +113,7 @@ quot: quot.o $(LIBOBJS)
repquota: repquota.o $(LIBOBJS)
warnquota: warnquota.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDAPLIBS)
quotastats: quotastats.o common.o pot.o
diff --git a/configure.in b/configure.in
index 49ce903..2d6445d 100644
--- a/configure.in
+++ b/configure.in
@@ -7,6 +7,16 @@ AC_HEADER_STDC
AC_PROG_INSTALL
dnl Checks for libraries.
+AC_ARG_WITH(ldapmail, [ --with-ldapmail=[yes/no/try] Enable ldap mail address lookups [default=no].],
+ ,
+ with_ldapmail="no")
+if test "x$with_ldapmail" != "xno"; then
+ LDAPLIBS="-L/usr/lib -lldap -llber -lssl -lresolv"
+ CFLAGS="$CFLAGS -DUSE_LDAP_MAIL_LOOKUP"
+fi
+AC_SUBST(LDAPLIBS)
+
+
AC_ARG_WITH(ext2direct,
[ --with-ext2direct=[yes/no/try] Enable alternative format used by edquota [default=try].],
,
diff --git a/quotacheck.8 b/quotacheck.8
index 0ce6187..470c2f2 100644
--- a/quotacheck.8
+++ b/quotacheck.8
@@ -53,7 +53,7 @@ This is most likely to happen after a system crash.
.PP
It is strongly recommended to run
.B quotacheck
-with quotas turned off on for the filesystem. Otherwise, possible damage
+with quotas turned off for the filesystem. Otherwise, possible damage
or loss to data in the quota files can result. It is also unwise to
run
.B quotacheck
diff --git a/quotacheck.c b/quotacheck.c
index fdd80cf..f452def 100644
--- a/quotacheck.c
+++ b/quotacheck.c
@@ -8,7 +8,7 @@
* New quota format implementation - Jan Kara <jack@suse.cz> - Sponsored by SuSE CR
*/
-#ident "$Id: quotacheck.c,v 1.35 2004/01/05 09:02:34 jkar8572 Exp $"
+#ident "$Id: quotacheck.c,v 1.36 2004/01/05 09:34:42 jkar8572 Exp $"
#include <dirent.h>
#include <stdio.h>
@@ -28,7 +28,6 @@
#include <sys/mount.h>
#if defined(EXT2_DIRECT)
-#include <linux/ext2_fs.h>
#include <ext2fs/ext2fs.h>
#endif
diff --git a/warnquota.c b/warnquota.c
index bf365f7..9fd68c8 100644
--- a/warnquota.c
+++ b/warnquota.c
@@ -10,7 +10,7 @@
*
* Author: Marco van Wieringen <mvw@planets.elm.net>
*
- * Version: $Id: warnquota.c,v 1.15 2003/10/12 11:42:37 jkar8572 Exp $
+ * Version: $Id: warnquota.c,v 1.16 2004/01/05 09:34:42 jkar8572 Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -29,6 +29,10 @@
#include <grp.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <time.h>
+#ifdef USE_LDAP_MAIL_LOOKUP
+#include <ldap.h>
+#endif
#include "mntopt.h"
#include "pot.h"
@@ -85,6 +89,10 @@ struct usage {
struct usage *next;
};
+#ifdef USE_LDAP_MAIL_LOOKUP
+LDAP *ldapconn = NULL;
+#endif
+
struct configparams {
char mail_cmd[CNF_BUFFER];
char from[CNF_BUFFER];
@@ -96,6 +104,18 @@ struct configparams {
char *user_signature;
char *group_message;
char *group_signature;
+ int use_ldap_mail; /* 0 */
+#ifdef USE_LDAP_MAIL_LOOKUP
+ int ldap_is_setup; /* 0 */
+ char ldap_host[CNF_BUFFER];
+ int ldap_port;
+ char ldap_binddn[CNF_BUFFER];
+ char ldap_bindpw[CNF_BUFFER];
+ char ldap_basedn[CNF_BUFFER];
+ char ldap_search_attr[CNF_BUFFER];
+ char ldap_mail_attr[CNF_BUFFER];
+ char default_domain[CNF_BUFFER];
+#endif /* USE_LDAP_MAIL_LOOKUP */
};
struct offenderlist {
@@ -117,6 +137,7 @@ struct adminstable {
};
int qtab_i = 0, fmt = -1, flags;
+char mailserv[CNF_BUFFER];
char *configfile = WARNQUOTA_CONF, *quotatabfile = QUOTATAB, *adminsfile = ADMINSFILE;
char *progname;
quotatable_t *quotatable;
@@ -128,6 +149,39 @@ struct adminstable *adminstable;
*/
static struct offenderlist *offenders = (struct offenderlist *)0;
+/*
+ * add any cleanup functions here
+ */
+static void wc_exit(int ex_stat)
+{
+#ifdef USE_LDAP_MAIL_LOOKUP
+ if(ldapconn != NULL)
+ ldap_unbind(ldapconn);
+#endif
+ exit(ex_stat);
+}
+
+#ifdef USE_LDAP_MAIL_LOOKUP
+static int setup_ldap(struct configparams *config)
+{
+ int ret;
+
+ ldapconn = ldap_init(config->ldap_host, config->ldap_port);
+ if(ldapconn == NULL) {
+ ldap_perror(ldapconn, "ldap_init");
+ return(-1);
+ }
+
+ ret = ldap_bind_s(ldapconn, config->ldap_binddn, config->ldap_bindpw, LDAP_AUTH_SIMPLE);
+ if(ret < 0) {
+ ldap_perror(ldapconn, "ldap_bind");
+ return(-1);
+ }
+ return(0);
+}
+
+#endif
+
struct offenderlist *add_offender(int type, int id, char *name)
{
struct offenderlist *offender;
@@ -174,11 +228,32 @@ void add_offence(struct dquot *dquot, char *name)
lptr->usage = usage;
}
+int deliverable(struct dquot *dquot)
+{
+ time_t now;
+
+ if((strlen(mailserv) == 0) || (strcasecmp(mailserv, "false") == 0))
+ return(1);
+
+ time(&now);
+
+ if (((dquot->dq_dqb.dqb_bhardlimit && toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit)
+ || ((dquot->dq_dqb.dqb_bsoftlimit && toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bsoftlimit)
+ && (dquot->dq_dqb.dqb_btime && dquot->dq_dqb.dqb_btime <= now)))
+ && ((strcasecmp(mailserv, "true") == 0)
+ || (strcasecmp(mailserv, dquot->dq_h->qh_quotadev) == 0)))
+ return(0);
+
+ return(1);
+}
+
int check_offence(struct dquot *dquot, char *name)
{
if ((dquot->dq_dqb.dqb_bsoftlimit && toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bsoftlimit)
- || (dquot->dq_dqb.dqb_isoftlimit && dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_isoftlimit))
- add_offence(dquot, name);
+ || (dquot->dq_dqb.dqb_isoftlimit && dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_isoftlimit)) {
+ if(deliverable(dquot))
+ add_offence(dquot, name);
+ }
return 0;
}
@@ -200,11 +275,11 @@ FILE *run_mailer(char *command)
close(pipefd[1]);
if (dup2(pipefd[0], 0) < 0) {
errstr(_("Can't duplicate descriptor: %s\n"), strerror(errno));
- exit(1);
+ wc_exit(1);
}
execl(SHELL, SHELL, "-c", command, NULL);
errstr(_("Can't execute '%s': %s\n"), command, strerror(errno));
- exit(1);
+ wc_exit(1);
default:
close(pipefd[0]);
if (!(f = fdopen(pipefd[1], "w")))
@@ -226,27 +301,111 @@ int mail_user(struct offenderlist *offender, struct configparams *config)
char timebuf[MAXTIMELEN];
char numbuf[3][MAXNUMLEN];
struct util_dqblk *dqb;
- char *to;
+ char *to = NULL, searchbuf[256];
+#ifdef USE_LDAP_MAIL_LOOKUP
+ LDAPMessage *result, *entry;
+ BerElement *ber = NULL;
+ struct berval **bvals = NULL;
+ int ret;
+ char *a;
+#endif
+
+ if (offender->offender_type == USRQUOTA) {
+#ifdef USE_LDAP_MAIL_LOOKUP
+ if(config->use_ldap_mail != 0) {
+ if((ldapconn == NULL) && (config->ldap_is_setup == 0)) {
+ /* need init */
+ if(setup_ldap(config)) {
+ errstr(_("Could not setup ldap connection, returning.\n"));
+ return -1;
+ }
+ config->ldap_is_setup = 1;
+ }
- if (offender->offender_type == USRQUOTA)
- to = offender->offender_name;
- else {
+ if(ldapconn == NULL) {
+ /* ldap was never setup correctly so just use the offender_name */
+ to = sstrdup(offender->offender_name);
+ } else {
+ /* search for the offender_name in ldap */
+ snprintf(searchbuf, 256, "(%s=%s)", config->ldap_search_attr,
+ offender->offender_name);
+ ret = ldap_search_s(ldapconn, config->ldap_basedn,
+ LDAP_SCOPE_SUBTREE, searchbuf,
+ NULL, 0, &result);
+ if(ret < 0) {
+ errstr(_("Error with %s.\n"), offender->offender_name);
+ ldap_perror(ldapconn, "ldap_search");
+ return 0;
+ }
+
+ cnt = ldap_count_entries(ldapconn, result);
+
+ if(cnt > 1) {
+ errstr(_("Multiple entries found for client %s, %d not sending mail.\n"),
+ offender->offender_name, cnt);
+ return 0;
+ } else if(cnt == 0) {
+ errstr(_("Entry not found for client %s, %d not sending mail.\n"),
+ offender->offender_name, cnt);
+ return 0;
+ } else {
+ /* get the attr */
+ entry = ldap_first_entry(ldapconn, result);
+ for(a = ldap_first_attribute(ldapconn, entry, &ber); a != NULL;
+ a = ldap_next_attribute( ldapconn, entry, ber)) {
+ if(strcasecmp(a, config->ldap_mail_attr) == 0) {
+ bvals = ldap_get_values_len(ldapconn, entry, a);
+ if(bvals == NULL) {
+ errstr(_("Could not get values for %s.\n"),
+ offender->offender_name);
+ return 0;
+ }
+ to = sstrdup(bvals[0]->bv_val);
+ break;
+ }
+ }
+
+ ber_bvecfree(bvals);
+ if(to == NULL) {
+ /*
+ * use just the name and default domain as we didn't find the
+ * attribute we wanted in this entry
+ */
+ to = malloc(strlen(offender->offender_name)+
+ strlen(config->default_domain)+1);
+ sprintf(to, "%s@%s", offender->offender_name,
+ config->default_domain);
+ }
+ }
+ }
+ } else {
+ to = sstrdup(offender->offender_name);
+ }
+#else
+ to = sstrdup(offender->offender_name);
+#endif
+ } else {
struct adminstable *admin;
if (!(admin = bsearch(offender->offender_name, adminstable, adminscnt, sizeof(struct adminstable), admin_name_cmp))) {
errstr(_("Administrator for a group %s not found. Cancelling mail.\n"), offender->offender_name);
return -1;
}
- to = admin->adminname;
+ to = sstrdup(admin->adminname);
}
- if (!(fp = run_mailer(config->mail_cmd)))
+ if (!(fp = run_mailer(config->mail_cmd))) {
+ if(to)
+ free(to);
return -1;
+ }
fprintf(fp, "From: %s\n", config->from);
fprintf(fp, "Reply-To: %s\n", config->support);
fprintf(fp, "Subject: %s\n", config->subject);
fprintf(fp, "To: %s\n", to);
fprintf(fp, "Cc: %s\n", config->cc_to);
fprintf(fp, "\n");
+ free(to);
+
if (offender->offender_type == USRQUOTA)
if (config->user_message)
fputs(config->user_message, fp);
@@ -431,7 +590,13 @@ int readconfigfile(const char *filename, struct configparams *config)
sstrncpy(config->cc_to, CC_TO, CNF_BUFFER);
sstrncpy(config->support, SUPPORT, CNF_BUFFER);
sstrncpy(config->phone, PHONE, CNF_BUFFER);
+ sstrncpy(mailserv, "false", CNF_BUFFER);
config->user_signature = config->user_message = config->group_signature = config->group_message = NULL;
+ config->use_ldap_mail = 0;
+
+#ifdef USE_LDAP_MAIL_LOOKUP
+ config->ldap_port = config->ldap_is_setup = 0;
+#endif
if (!(fp = fopen(filename, "r"))) {
errstr(_("Can't open %s: %s\n"), filename, strerror(errno));
@@ -487,7 +652,10 @@ int readconfigfile(const char *filename, struct configparams *config)
sstrncpy(config->support, value, CNF_BUFFER);
else if (!strcmp(var, "PHONE"))
sstrncpy(config->phone, value, CNF_BUFFER);
- else if (!strcmp(var, "MESSAGE")) {
+ else if (!strcmp(var, "MAILSERV")) {
+ /* set the global */
+ sstrncpy(mailserv, value, CNF_BUFFER);
+ } else if (!strcmp(var, "MESSAGE")) {
config->user_message = sstrdup(value);
create_eoln(config->user_message);
}
@@ -503,6 +671,30 @@ int readconfigfile(const char *filename, struct configparams *config)
config->group_signature = sstrdup(value);
create_eoln(config->group_signature);
}
+ else if (!strcmp(var, "LDAP_MAIL")) {
+ if(strcasecmp(value, "true") == 0)
+ config->use_ldap_mail = 1;
+ else
+ config->use_ldap_mail = 0;
+ }
+#ifdef USE_LDAP_MAIL_LOOKUP
+ else if (!strcmp(var, "LDAP_HOST"))
+ sstrncpy(config->ldap_host, value, CNF_BUFFER);
+ else if (!strcmp(var, "LDAP_PORT"))
+ config->ldap_port = (int)strtol(value, NULL, 10);
+ else if(!strcmp(var, "LDAP_BINDDN"))
+ sstrncpy(config->ldap_binddn, value, CNF_BUFFER);
+ else if(!strcmp(var, "LDAP_BINDPW"))
+ sstrncpy(config->ldap_bindpw, value, CNF_BUFFER);
+ else if(!strcmp(var, "LDAP_BASEDN"))
+ sstrncpy(config->ldap_basedn, value, CNF_BUFFER);
+ else if(!strcmp(var, "LDAP_SEARCH_ATTRIBUTE"))
+ sstrncpy(config->ldap_search_attr, value, CNF_BUFFER);
+ else if(!strcmp(var, "LDAP_MAIL_ATTRIBUTE"))
+ sstrncpy(config->ldap_mail_attr, value, CNF_BUFFER);
+ else if(!strcmp(var, "LDAP_DEFAULT_MAIL_DOMAIN"))
+ sstrncpy(config->default_domain, value, CNF_BUFFER);
+#endif
else /* not matched at all */
errstr(_("Error in config file (line %d), ignoring\n"), line);
}
@@ -585,9 +777,9 @@ void warn_quota(void)
int i;
if (readconfigfile(configfile, &config) < 0)
- exit(1);
+ wc_exit(1);
if (get_quotatable() < 0)
- exit(1);
+ wc_exit(1);
if (flags & FL_USER) {
handles = create_handle_list(0, NULL, USRQUOTA, -1, IOI_LOCALONLY | IOI_READONLY | IOI_OPENFILE, (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0));
@@ -597,14 +789,14 @@ void warn_quota(void)
}
if (flags & FL_GROUP) {
if (get_groupadmins() < 0)
- exit(1);
+ wc_exit(1);
handles = create_handle_list(0, NULL, GRPQUOTA, -1, IOI_LOCALONLY | IOI_READONLY | IOI_OPENFILE, (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0));
for (i = 0; handles[i]; i++)
handles[i]->qh_ops->scan_dquots(handles[i], check_offence);
dispose_handle_list(handles);
}
if (mail_to_offenders(&config) < 0)
- exit(1);
+ wc_exit(1);
}
/* Print usage information */
@@ -612,7 +804,7 @@ static void usage(void)
{
errstr(_("Usage:\n warnquota [-ugsid] [-F quotaformat] [-c configfile] [-q quotatabfile]\n"));
fprintf(stderr, _("Bugs to %s\n"), MY_EMAIL);
- exit(1);
+ wc_exit(1);
}
static void parse_options(int argcnt, char **argstr)
@@ -629,7 +821,7 @@ static void parse_options(int argcnt, char **argstr)
break;
case 'F':
if ((fmt = name2fmt(optarg)) == QF_ERROR)
- exit(1);
+ wc_exit(1);
break;
case 'c':
configfile = optarg;
@@ -670,5 +862,5 @@ int main(int argc, char **argv)
init_kernel_interface();
warn_quota();
- return 0;
+ wc_exit(0);
}
diff --git a/warnquota.conf b/warnquota.conf
index b31fef2..ee8a24d 100644
--- a/warnquota.conf
+++ b/warnquota.conf
@@ -27,5 +27,32 @@ I chose you to do the cleanup.|Delete group files on following filesystems:|
# and PHONE is created).
GROUP_SIGNATURE = See you!| Your admin|
#
+#If you are running warnquota on a mail server, and don't want bounces
+#because clients can not receive mail setting this to true will cause
+#warnquota to not send them mail for all devices. If you set this to the
+#device name (for example /dev/hdb1) then they will not be sent mail if they
+#are overquota on that device only, and will be sent mail for all other
+#devices.
+#MAILSERV = "false"
+#
+# If you are using LDAP mail lookups.
+# host, port, tls, binddn, and bindpw are straight forward.
+# LDAP_BASEDN is your search base dn
+# LDAP_SEARCH_ATTRIBUTE is the attr for the value you are looking for
+# LDAP_MAIL_ATTRIBUTE is the attribute you want used for the mail address
+# LDAP_DEFAULT_MAIL_DOMAIN is the default domain
+# if the attribute isn't found
+# if binddn and bindpw are blank or left out, an anonymous bind is used
+#
+# LDAP_MAIL = false # or false if you don't want to use it
+# LDAP_HOST = ldap
+# LDAP_PORT = 389
+# LDAP_BINDDN = uid=ReadOnlyUser,o=YourOrg
+# LDAP_BINDPW = YourReadOnlyUserPassword
+# LDAP_BASEDN = YourSearchBase
+# LDAP_SEARCH_ATTRIBUTE = uid
+# LDAP_MAIL_ATTRIBUTE = mailLocalAddress
+# LDAP_DEFAULT_MAIL_DOMAIN = YourDefaultMailDomain.com
+#
# end of example warnquota.conf file
#