diff options
author | jkar8572 <jkar8572> | 2004-01-05 09:34:42 +0000 |
---|---|---|
committer | jkar8572 <jkar8572> | 2004-01-05 09:34:42 +0000 |
commit | 07c4d96601d69b589321316a2c46cc839d2448b2 (patch) | |
tree | cb07ac47bce6cfe8cc32ffb1ff8ccac386db2641 | |
parent | ac836075998abb743c0f53f66d45db2d504f5485 (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-- | Changelog | 4 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | configure.in | 10 | ||||
-rw-r--r-- | quotacheck.8 | 2 | ||||
-rw-r--r-- | quotacheck.c | 3 | ||||
-rw-r--r-- | warnquota.c | 230 | ||||
-rw-r--r-- | warnquota.conf | 27 |
7 files changed, 256 insertions, 22 deletions
@@ -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 # |