tjh@cel.uucp (tim howard) (06/04/90)
Program "authorise" for use with "sendmail" =========================================== Introduction ============ Along with the Sendmail Configuration Package UK-2.1, in the "support" directory, I received "authorise". I have recently tried to use this for the first time. It did not appear to have the desired effect. When called from "sendmail.cf" it is passed more parameters than the original version of "authorise" used to determine the "to_addr" ( destination address ). "authorise.c" has been modified to use one of these additional parameters as its "to_addr". The modified version seems to give more meaningful results in this application. The Application =============== In order to modify the sendmail.cf file I used the UK-2.1 package by adding ",auth" to one line in "config.server2" ( Crosfield specific ) as follows :- channel uucp file="randd.uucp.chn",ldomain="cel.uucp",sysname="server2",auth This resulted in the following pair of lines ( split for this message ) in "sendmail.cf" :- Muucp, F=sFDMuh, S=23, R=23, M=300000, P=/usr/lib/authorise, A=authorise uucp $g $h /usr/bin/uux - -r -gA $h!rmail ($u) The Analysis ============ "authorise.c" was modified to print the command line arguments to a file. This typically produced :- Command line arguments ( argv ) are:- uucp cel.uucp!tjh stl /usr/bin/uux - -r -gA stl!rmail (nowhere.co.uk!infoserver) From which it can be seen that the augument immediately after the "from_addr" ( who is sending ) is, in this case, the single word "stl", and that further along the list is the longer "(nowhere.co.uk!infoserver)". If the purpose of running "authorise" is, for example, to prevent users sending to info-servers then, although "stl" may be regarded as a valid "to_addr" the system will not work as intended if left as it was. The Fix ======= The main "fix" is to use the 9th parameter rather than the 3rd as the "to_addr". In addition, originally for debugging, a log file has been introduced. Here is the source code ( 267 lines with not much after it except a plea for comments ) :- ------------------------------------------------------------------------------ /* * authorise - sendmail authorisation program * * Given a channel name, sender address and recipient address or * host, it matches these against entries in an authorisation * file to see if permission is granted to send the mail. * * If successful, the mailer interface is called; else the * appropriate error status is returned to sendmail. * * Written by Jim Crammond. <jac@ic.doc> 5/87 * major modifications Tim Howard / A Gray (cel) June 90 */ #include <stdio.h> #include <sysexits.h> #include <sys/types.h> /* for ascii_timenow */ #include <sys/time.h> /* for ascii_timenow */ #define AUTHFILE "/usr/lib/authorisations" /*** #define DEBUG ***/ #define LOGGING #define LOG_FILE "/usr/spool/uucp/auth_debug" /* addition TJH */ #define CHANSIZE 64 #define ADDRSIZE 256 #define LINESIZE 1024 char a_chan[CHANSIZE]; char a_from[ADDRSIZE]; char a_to[ADDRSIZE]; char *authfile = AUTHFILE; char str[26]; /* for ascii_timenow */ char* ascii_timenow(); /* needed before a call to it */ int negative = 0; main(argc, argv) int argc; char *argv[]; { char *progname, *channel; char *from_addr, *to_addr; FILE *afp, *fopen(); FILE *log_file; /* addition TJH */ char line[LINESIZE]; int cnt, nfields,i; register char *p; char *index(); int gotmatch = 0; extern int errno; progname = *argv++; #ifdef LOGGING if ((log_file = fopen(LOG_FILE, "a")) == NULL) { printf("%s: warning: cannot open debug file\n",progname); exit(errno); } fprintf(log_file,"----------------------------------------------------------------------------\n"); fprintf(log_file,"%s \n", ascii_timenow()); /* fprintf(log_file,"Command line arguments ( argv ) are:- "); * for(i=0;argv[i] != NULL;i++) fprintf(log_file,"%s ",argv[i]); * fprintf(log_file,"\n"); */ #endif LOGGING if (argv[0][0] == '-' && argv[0][1] == 'f') { authfile = argv[1]; argc -= 2; argv += 2; } if (argc < 4) { printf("usage: %s [-f authfile] channel from to command [args]\n", progname); #ifdef LOGGING fclose(log_file); #endif LOGGING exit(EX_USAGE); } channel = *argv++; from_addr = *argv++; to_addr = *argv++; /************ Major change at Crosfield Electronics Ltd ( cel ) follows ********* * * when called from UK2.1 sendmail.cf the "to_addr" is not the next argument * after the "from_addr" * ( but the pointer does need to have been incremented ) * there will be 9 arguments ( no -f authfile ? ) and hence argc here will be 10 * */ if ( argc == 10 ) { to_addr = argv[5]; } /************ end of major change at "cel" *****************/ if ((afp = fopen(authfile, "r")) == NULL) { printf("warning: cannot open authorisation file\n"); gotmatch = 1; } while (!gotmatch && fgets(line, sizeof(line), afp)) { cnt++; if ((p = index(line, '\n')) != NULL) *p = '\0'; if ((p = index(line, '#')) != NULL) *p = '\0'; for (p=line; *p == ' ' && *p == '\t'; p++) ; if (*p == '\0') continue; nfields = sscanf(p, "%s %s %s", a_chan, a_from, a_to); if (nfields != 3) { printf("warning: line %d ignored: \"%s\"\n", cnt, line); continue; } negative = 0; if (strcmp(channel, a_chan) == 0 && match(from_addr, a_from) && match(to_addr, a_to)) { if (negative > 0) gotmatch = -1; else gotmatch = 1; } #ifdef DEBUG printf("%d: %s - %s\n", cnt, line, gotmatch ? "matched" : "no match"); #endif DEBUG } #ifdef LOGGING fprintf(log_file,"%s %s line=%d ", progname, authfile, cnt ); switch(gotmatch) { case 1: fprintf(log_file," authorised "); break; case 0: fprintf(log_file," denied_by_default " ); break; default: fprintf(log_file," actively_denied " ); break; } fprintf(log_file," %s %s \n", from_addr, to_addr ); #endif LOGGING if (gotmatch <= 0) { printf("%s: %s is not authorised to send to host/address %s\n", progname, from_addr, to_addr); #ifdef LOGGING fclose(log_file); #endif LOGGING exit(EX_NOPERM); } #ifdef LOGGING /* fprintf(log_file,"About to try to execute "); * for(i=0;argv[i] != NULL;i++) fprintf(log_file,"%s ",argv[i]); * fprintf(log_file,"\n"); */ fclose(log_file); #endif LOGGING execv(argv[0], argv); printf("%s: cannot exec %s\n", progname, argv[0]); exit(EX_UNAVAILABLE); } /* * MATCH -- match the strings s1 and s2. * s2 can contain wildcards and lists */ match(s1, s2) char *s1, *s2; { char lbuf[ADDRSIZE]; char *rest, *lp; char *index(); if (*s2 == '\\') /* escape */ { if (*s1 == *(s2+1) && match(s1+1, s2+2)) return(1); } else if (*s2 == '*') /* wildcard */ { if (match(s1, ++s2)) return(1); while (*s1++) { if (match(s1, s2)) return(1); } } else if (*s2 == '{' && (rest = index(++s2, '}'))) /* list */ { rest++; lp = lbuf; while (s2 != rest) { while (*s2 && *s2 != ',' && *s2 != '}') *lp++ = *s2++; strcpy(lp, rest); if (match(s1, lbuf)) return(1); lp = lbuf; s2++; } } else if (*s2 == '^') /* negative match */ { if (match(s1, ++s2)) { negative++; return(1); } } else if (*s1 == *s2) /* literal */ { if (*s1 == '\0') return(1); if (match(++s1, ++s2)) return(1); } return(0); } /* --------------------------------------------------------------------- */ /* ASCII_TIMENOW .. return a pointer to an ascii string containing the current date and time in date(1) format A. Gray 21/5/90 */ char* ascii_timenow() { time_t stime,timenow; struct tm *ltime; int time(); stime = time(0); /* get current system time */ ltime = localtime(&stime); /* apply any local time offset inc DST */ strcpy(str,asctime(ltime)); /* convert to a printable string */ str[24] = '\0'; /* delete the newline that asctime puts on */ return(str); } ------------------------------------------------------------------------------ Comments please. -- Tim Howard Crosfield Electronics Ltd ( cel ) Voice 0442-230000 x 3406