diff options
| author | Theodore Tso <tytso@mit.edu> | 1994-08-09 02:13:15 +0000 |
|---|---|---|
| committer | Theodore Tso <tytso@mit.edu> | 1994-08-09 02:13:15 +0000 |
| commit | 8404900f651f30e54ac908bf54d1e2eb3c6d630d (patch) | |
| tree | 45d1f0e40d3ab1881c65f0eb9cd828eab8133a5b /src | |
| parent | aa9d934827a728b1cc43571f57608f2e6ad827dc (diff) | |
Added John Brezak's port of mailquery to krb5
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4073 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
| -rw-r--r-- | src/appl/mailquery/Makefile.in | 23 | ||||
| -rw-r--r-- | src/appl/mailquery/configure.in | 7 | ||||
| -rw-r--r-- | src/appl/mailquery/mailquery.M | 41 | ||||
| -rw-r--r-- | src/appl/mailquery/mailquery.c | 174 | ||||
| -rw-r--r-- | src/appl/mailquery/pop.h | 35 | ||||
| -rw-r--r-- | src/appl/mailquery/poplib.c | 493 |
6 files changed, 773 insertions, 0 deletions
diff --git a/src/appl/mailquery/Makefile.in b/src/appl/mailquery/Makefile.in new file mode 100644 index 000000000..9261a9923 --- /dev/null +++ b/src/appl/mailquery/Makefile.in @@ -0,0 +1,23 @@ +CFLAGS = $(CCOPTS) -DKPOP -DKRB5 $(DEFS) $(LOCALINCLUDE) + +all:: + +KLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(ISODELIB) $(COMERRLIB) $(DBMLIB) + +HESIODLIB = + +mailquery: mailquery.o poplib.o + $(CC) $(CFLAGS) -o mailquery mailquery.o poplib.o $(KLIB) $(HESIODLIB) + +mailquery.o: $(srcdir)/mailquery.c +poplib.o: $(srcdir)/poplib.c + +all:: mailquery + +clean:: + $(RM) mailquery.o poplib.o mailquery + +install:: + cp mailquery ${DESTDIR}$(CLIENT_BINDIR)/mailquery + cp mailquery.M ${DESTDIR}$(CLIENT_MANDIR)/mailquery.1 + diff --git a/src/appl/mailquery/configure.in b/src/appl/mailquery/configure.in new file mode 100644 index 000000000..367353214 --- /dev/null +++ b/src/appl/mailquery/configure.in @@ -0,0 +1,7 @@ +AC_INIT(mailquery.c) +WITH_CCOPTS +AC_SET_BUILDTOP +CONFIG_RULES +AC_FUNC_CHECK(strerror,AC_DEFINE(HAS_STRERROR)) +KRB_INCLUDE +AC_OUTPUT(Makefile,[EXTRA_RULES]) diff --git a/src/appl/mailquery/mailquery.M b/src/appl/mailquery/mailquery.M new file mode 100644 index 000000000..113146f40 --- /dev/null +++ b/src/appl/mailquery/mailquery.M @@ -0,0 +1,41 @@ +.\" +.\" (c) Copyright 1994 HEWLETT-PACKARD COMPANY +.\" +.\" To anyone who acknowledges that this file is provided +.\" "AS IS" without any express or implied warranty: +.\" permission to use, copy, modify, and distribute this +.\" file for any purpose is hereby granted without fee, +.\" provided that the above copyright notice and this +.\" notice appears in all copies, and that the name of +.\" Hewlett-Packard Company not be used in advertising or +.\" publicity pertaining to distribution of the software +.\" without specific, written prior permission. Hewlett- +.\" Packard Company makes no representations about the +.\" suitability of this software for any purpose. +.\" +.\" $Id +.\" +.TH mailquery 1 +.SH NAME +mailquery \- queries a pop server about how much mail is available +.SH SYNTAX +.B mailquery +[-\fId\fR\|] +[-\fIv\fR\|] +[\fI user\fR[@\fIhost\fR\|]] +.SH DESCRIPTION +The +.PN mailquery +command queries a POP server for information about how much mail a user +has. The program will exit with status = 0 if there is mail, and with +status = 1 if there is no mail. The -v flag can be used to get a more +verbose report. The -d flag can be used to turn on debugging output +in the pop library code. The pop server can be specified either by +setting the environment variable MAILHOST, or on the command line. +If no user is specified, user is set to the person who ran the program. +.SH OPTIONS + +.SH BUGS/LIMITATIONS + +.SH SEE ALSO +popper(8) diff --git a/src/appl/mailquery/mailquery.c b/src/appl/mailquery/mailquery.c new file mode 100644 index 000000000..6f4d0b274 --- /dev/null +++ b/src/appl/mailquery/mailquery.c @@ -0,0 +1,174 @@ +/* + * (c) Copyright 1994 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided + * "AS IS" without any express or implied warranty: + * permission to use, copy, modify, and distribute this + * file for any purpose is hereby granted without fee, + * provided that the above copyright notice and this + * notice appears in all copies, and that the name of + * Hewlett-Packard Company not be used in advertising or + * publicity pertaining to distribution of the software + * without specific, written prior permission. Hewlett- + * Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * Mailquery - contact the POP mail host an see if a user has + * mail. By default the result if reflected in the + * exit status. + * + * Usage: mailquery [-dv] [-e <cmd>] + * -d - debug + * -v - print result + * -e - exec this command if there is mail. + */ +#include <pwd.h> +#include <fcntl.h> +#include <sys/file.h> +#include <stdio.h> +#ifdef HESIOD +#include <hesiod.h> +#endif +#include "pop.h" + + +extern int pop_debug; +int verbose = 0; +char *exec_cmd; + +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *getenv(); + int nbytes; + char *mhost = NULL, *mhp; + char *user = 0; + struct passwd * pwd; + char response[128]; + char c; + extern int optind; + extern char *optarg; +#ifdef HESIOD + struct hes_postoffice *p; +#endif /* HESIOD */ + char *index(); + + while ((c = getopt(argc, argv, "dve:")) != EOF) { + switch (c) { + case 'd': + pop_debug = 1; + break; + + case 'e': + exec_cmd = optarg; + break; + + case 'v': + verbose = 1; + break; + + case '?': + usage(); + exit(1); + } + } + + argc -= optind; + argv += optind; + + if (argc > 0) { + user = argv[0]; + if ((mhost = index(argv[0], '@')) != NULL) { + *mhost = '\0'; + mhost++; + } +#ifndef HESIOD + else { + mhost = DEFMAILHOST; + } +#endif + } + + if (user == (char *) 0 || *user == '\0') { + if ((pwd = getpwuid(getuid())) == NULL) { + perror("getpwuid"); + exit(1); + } + user = pwd->pw_name; + } + + if ((mhost == NULL) && + (mhp = getenv("MAILHOST"))) + mhost = mhp; + +#ifdef HESIOD + if (mhost == NULL) { + p = hes_getmailhost(user); + if (p != NULL && strcmp(p->po_type, "POP") == 0) + mhost = p->po_host; + else { + fprintf(stderr,"no POP server listed in Hesiod for %s\n", user); + exit(1); + } + } +#endif /* HESIOD */ + + if (mhost == NULL) { + mhost = DEFMAILHOST; + } + + nbytes = mailquery(mhost, user); + + if ((nbytes > 0) && (exec_cmd != 0)) { + if (pop_debug) + fprintf(stderr, "about to execute %s\n", exec_cmd); + system(exec_cmd); + } + + exit(nbytes == 0); + +} + +mailquery(mhost, user) + char *mhost; + char *user; +{ + int nbytes, nmsgs; + + if (pop_init(mhost, 0) == NOTOK) { + error(Errmsg); + exit(1); + } + +#ifdef KPOP + if (pop_command("USER %s", user) == NOTOK || + pop_command("PASS %s", user) == NOTOK) { +#else /* !KPOP */ + if (pop_command("USER %s", user) == NOTOK || + pop_command("RPOP %s", user) == NOTOK) { +#endif /* KPOP */ + error(Errmsg); + (void) pop_command("QUIT"); + exit (1); + } + + if (pop_stat(&nmsgs, &nbytes) == NOTOK) { + error(Errmsg); + (void) pop_command("QUIT"); + exit (1); + } + + if (verbose) + printf("%d messages (%d bytes) on host %s\n", nmsgs, nbytes, mhost); + + return nbytes; +} + +usage() +{ + fprintf(stderr, "usage: mailquery [-d] [-v] [-e cmd] [user[@host]]\n"); +} + + diff --git a/src/appl/mailquery/pop.h b/src/appl/mailquery/pop.h new file mode 100644 index 000000000..e7ffc4ff2 --- /dev/null +++ b/src/appl/mailquery/pop.h @@ -0,0 +1,35 @@ +/* + * (c) Copyright 1994 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided + * "AS IS" without any express or implied warranty: + * permission to use, copy, modify, and distribute this + * file for any purpose is hereby granted without fee, + * provided that the above copyright notice and this + * notice appears in all copies, and that the name of + * Hewlett-Packard Company not be used in advertising or + * publicity pertaining to distribution of the software + * without specific, written prior permission. Hewlett- + * Packard Company makes no representations about the + * suitability of this software for any purpose. + * + * $Id$ + * + */ + +/* defines for pop library */ + +#define NOTOK (-1) +#define OK 0 +#define DONE 1 + +#define DEFMAILHOST "mailhost" + +int pop_init(), pop_getline(); +char *get_errmsg(); +int pop_command(); +int pop_stat(); +int pop_retr(); +char *concat(); + +extern char Errmsg[]; diff --git a/src/appl/mailquery/poplib.c b/src/appl/mailquery/poplib.c new file mode 100644 index 000000000..2b4c8633a --- /dev/null +++ b/src/appl/mailquery/poplib.c @@ -0,0 +1,493 @@ +/* + * (c) Copyright 1994 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided + * "AS IS" without any express or implied warranty: + * permission to use, copy, modify, and distribute this + * file for any purpose is hereby granted without fee, + * provided that the above copyright notice and this + * notice appears in all copies, and that the name of + * Hewlett-Packard Company not be used in advertising or + * publicity pertaining to distribution of the software + * without specific, written prior permission. Hewlett- + * Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +#if !defined(lint) && !defined(_NOIDENT) +static char rcsid[] = "@(#)$Header$"; +#endif +/* + * Poplib - library routines for speaking POP + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <errno.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <stdio.h> +#if defined(KRB4) && defined(KRB5) +# error You cannot define both KRB4 and KRB5 +#endif +#ifndef KPOP_SERVICE +#define KPOP_SERVICE "kpop" +#endif +#ifdef KPOP +#ifdef KRB4 +#include <krb.h> +#endif +#ifdef KRB5 +#include <krb5/krb5.h> +#include <krb5/ext-proto.h> +#include <krb5/los-proto.h> +#include <com_err.h> +#include <ctype.h> +#endif +#endif + +#include "pop.h" + +void *xmalloc(); + +char Errmsg[80]; /* to return error messages */ +int pop_debug; + +static FILE *sfi = 0; +static FILE *sfo = 0; + +pop_init(host, reserved) +char *host; +int reserved; +{ + register struct hostent *hp; + register struct servent *sp; + int lport = IPPORT_RESERVED - 1; + struct sockaddr_in sin; + int s; + char *get_errmsg(); + char response[1024]; + char *routine; +#ifdef KPOP +#ifdef KRB4 + CREDENTIALS cred; + KTEXT ticket = (KTEXT)NULL; + int rem; +#endif +#ifdef KRB5 + krb5_error_code retval; + krb5_ccache ccdef; + krb5_principal client = NULL, server = NULL; + krb5_error *err_ret = NULL; + register char *cp; +#endif +#endif + + if (sfi && sfo) { + return; + } + + hp = gethostbyname(host); + if (hp == NULL) { + sprintf(Errmsg, "MAILHOST unknown: %s", host); + return(NOTOK); + } + +#ifdef KPOP + sp = getservbyname(KPOP_SERVICE, "tcp"); + if (sp == 0) { + (void) strcpy(Errmsg, "tcp/kpop: unknown service"); + return(NOTOK); + } +#else /* !KPOP */ + sp = getservbyname("pop", "tcp"); + if (sp == 0) { + (void) strcpy(Errmsg, "tcp/pop: unknown service"); + return(NOTOK); + } +#endif /* KPOP */ + if (sp == 0) { + strcpy(Errmsg, "tcp/pop: unknown service"); + return(NOTOK); + } + + sin.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); + sin.sin_port = sp->s_port; +#ifdef KPOP + s = socket(AF_INET, SOCK_STREAM, 0); +#else /* !KPOP */ + if (reserved) + s = rresvport(&lport); + else + s = socket(AF_INET, SOCK_STREAM, 0); +#endif /* KPOP */ + + if (s < 0) { + sprintf(Errmsg, "error creating socket: %s", get_errmsg()); + return(NOTOK); + } + + if (connect(s, (struct sockaddr *)&sin, sizeof sin) < 0) { + sprintf(Errmsg, "error during connect: %s", get_errmsg()); + close(s); + return(NOTOK); + } + +#ifdef KPOP +#ifdef KRB4 + /* Get tgt creds from ticket file. This is used to calculate the + * lifetime for the pop ticket so that it expires with the + * tgt */ + rem = krb_get_cred("krbtgt", krb_realmofhost(hp->h_name), krb_realmofhost(hp->h_name), &cred); + if (rem == KSUCCESS) { + long lifetime; + lifetime = ((cred.issue_date + ((unsigned char)cred.lifetime * 5 * 60)) - time(0)) / (5 * 60); + if (lifetime > 0) + krb_set_lifetime(lifetime); + } + ticket = (KTEXT)malloc( sizeof(KTEXT_ST) ); + rem = krb_sendauth(0L, s, ticket, "pop", hp->h_name, (char *)0, + 0, (MSG_DAT *) 0, (CREDENTIALS *) 0, + (bit_64 *) 0, (struct sockaddr_in *)0, + (struct sockaddr_in *)0,"ZMAIL0.0"); + if (rem != KSUCCESS) { + (void) sprintf(Errmsg, "kerberos error: %s",krb_err_txt[rem]); + (void) close(s); + return(NOTOK); + } +#endif /* KRB4 */ +#ifdef KRB5 + krb5_init_ets(); + + routine = "krb5_cc_default"; + if (retval = krb5_cc_default(&ccdef)) { + krb5error: + sprintf(Errmsg, "%s: krb5 error: %s", routine, error_message(retval)); + close(s); + return(NOTOK); + } + routine = "krb5_cc_get_principal"; + if (retval = krb5_cc_get_principal(ccdef, &client)) { + goto krb5error; + } + +#if 0 + /* lower-case to get name for "instance" part of service name */ + for (cp = hp->h_name; *cp; cp++) + if (isupper(*cp)) + *cp = tolower(*cp); +#endif + + routine = "krb5_sname_to_principal"; + if (retval = krb5_sname_to_principal(hp->h_name, "pop", + KRB5_NT_UNKNOWN, + &server)) { + goto krb5error; + } + + retval = krb5_sendauth((krb5_pointer) &s, "KPOPV1.0", client, server, + AP_OPTS_MUTUAL_REQUIRED, + 0, /* no checksum */ + 0, /* no creds, use ccache instead */ + ccdef, + 0, /* don't need seq # */ + 0, /* don't need a subsession key */ + &err_ret, + 0); /* don't need reply */ + krb5_free_principal(server); + if (retval) { + if (err_ret && err_ret->text.length) { + sprintf(Errmsg, "krb5 error: %s [server says '%*s'] ", + error_message(retval), + err_ret->text.length, + err_ret->text.data); + krb5_free_error(err_ret); + } else + sprintf(Errmsg, "krb5_sendauth: krb5 error: %s", error_message(retval)); + close(s); + return(NOTOK); + } +#endif /* KRB5 */ +#endif /* KPOP */ + + sfi = fdopen(s, "r"); + sfo = fdopen(s, "w"); + if (sfi == NULL || sfo == NULL) { + sprintf(Errmsg, "error in fdopen: %s", get_errmsg()); + close(s); + return(NOTOK); + } + + if (getline(response, sizeof response, sfi) != OK) { + error(response); + return(NOTOK); + } + if (pop_debug) + fprintf(stderr, "<--- %s\n", response); + + return(OK); +} + +pop_command(fmt, a, b, c, d) +char *fmt; +{ + char buf[1024]; + char errmsg[64]; + + sprintf(buf, fmt, a, b, c, d); + + if (pop_debug) fprintf(stderr, "---> %s\n", buf); + if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return(NOTOK); + } + + if (pop_debug) fprintf(stderr, "<--- %s\n", buf); + if (*buf != '+') { + strcpy(Errmsg, buf); + return(NOTOK); + } else { + return(OK); + } +} + +pop_query(nbytes, user) + int *nbytes; + char *user; +{ + char buf[1024]; + + if (strlen(user) > 120) { + if (pop_debug) fprintf(stderr, "username %s too long\n", user); + return NOTOK; + } + + sprintf(buf, "QUERY %s", user); + if (pop_debug) fprintf(stderr, "---> %s\n", buf); + if (putline(buf, Errmsg, sfo) == NOTOK) return (NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return NOTOK; + } + + if (pop_debug) fprintf(stderr, "<--- %s\n", buf); + if (*buf != '+') { + strcpy(Errmsg, buf); + return NOTOK; + } else { + sscanf(buf, "+OK %d", nbytes); + return OK; + } +} + +pop_stat(nmsgs, nbytes) +int *nmsgs, *nbytes; +{ + char buf[1024]; + + if (pop_debug) fprintf(stderr, "---> STAT\n"); + if (putline("STAT", Errmsg, sfo) == NOTOK) return(NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return(NOTOK); + } + + if (pop_debug) fprintf(stderr, "<--- %s\n", buf); + if (*buf != '+') { + strcpy(Errmsg, buf); + return(NOTOK); + } else { + sscanf(buf, "+OK %d %d", nmsgs, nbytes); + return(OK); + } +} + +pop_retr(msgno, action, arg) +int (*action)(); +{ + char buf[1024]; + int nbytes = 0; + + sprintf(buf, "RETR %d", msgno); + + if (pop_debug) + fprintf(stderr, "---> %s\n", buf); + + if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK); + + if (getline(buf, sizeof buf, sfi) != OK) { + strcpy(Errmsg, buf); + return(NOTOK); + } + if (pop_debug) + fprintf(stderr, "<--- %s\n", buf); + + sscanf(buf, "+OK %d", &nbytes); + + while (1) { + switch (multiline(buf, sizeof buf, sfi)) { + case OK: + if ((*action)(buf, arg, nbytes) < 0) { + strcat(Errmsg, get_errmsg()); + return (DONE); /* Some error occured in action */ + } + break; + case DONE: + return (OK); + case NOTOK: + strcpy(Errmsg, buf); + return (NOTOK); + } + } +} + +pop_getline(buf, n) + char *buf; + int n; +{ + return getline(buf, n, sfi); +} + +getline(buf, n, f) +char *buf; +register int n; +FILE *f; +{ + register char *p; + int c; + + p = buf; + while (--n > 0 && (c = fgetc(f)) != EOF) + if ((*p++ = c) == '\n') break; + + if (ferror(f)) { + strcpy(buf, "error on connection"); + return (NOTOK); + } + + if (c == EOF && p == buf) { + strcpy(buf, "connection closed by foreign host"); + return (DONE); + } + + *p = NULL; + if (*--p == '\n') *p = NULL; + if (*--p == '\r') *p = NULL; + return(OK); +} + +multiline(buf, n, f) +char *buf; +register int n; +FILE *f; +{ + if (getline(buf, n, f) != OK) return (NOTOK); + if (*buf == '.') { + if (*(buf+1) == NULL) { + return (DONE); + } else { + strcpy(buf, buf+1); + } + } + return(OK); +} + +#ifndef HAS_STRERROR +char * +strerror(e) + int e; +{ + extern int errno, sys_nerr; + extern char *sys_errlist[]; + + if (errno < sys_nerr) + s = sys_errlist[errno]; + else + s = "unknown error"; +} +#endif + +char * +get_errmsg() +{ + char *s = strerror(errno); + + return(s); +} + +putline(buf, err, f) +char *buf; +char *err; +FILE *f; +{ + fprintf(f, "%s\r\n", buf); + fflush(f); + if (ferror(f)) { + strcpy(err, "lost connection"); + return(NOTOK); + } + return(OK); +} + + +/* Print error message and exit. */ + +fatal (s1, s2) + char *s1, *s2; +{ + error (s1, s2); + exit (1); +} + +/* Print error message. `s1' is printf control string, `s2' is arg for it. */ + +error (s1, s2, s3) + char *s1, *s2, *s3; +{ + printf ("poplib: "); + printf (s1, s2, s3); + printf ("\n"); +} + +pfatal_with_name (name) + char *name; +{ + char *s = concat ("", strerror(errno), " for %s"); + + fatal (s, name); +} + +/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ + +char * +concat (s1, s2, s3) + char *s1, *s2, *s3; +{ + int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); + char *result = (char *) xmalloc (len1 + len2 + len3 + 1); + + strcpy (result, s1); + strcpy (result + len1, s2); + strcpy (result + len1 + len2, s3); + *(result + len1 + len2 + len3) = 0; + + return result; +} + +/* Like malloc but get fatal error if memory is exhausted. */ + +void * +xmalloc (size) + int size; +{ + void *result = malloc (size); + if (!result) + fatal ("virtual memory exhausted", 0); + return result; +} |
