home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Filename: pgpsendmail.c $
- * $Revision: 1.45 $
- * $Date: 1994/03/21 14:54:52 $
- *
- * Copyright (C) 1993 by Peter Simons <simons@peti.GUN.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: pgpsendmail.c,v 1.45 1994/03/21 14:54:52 simons Exp simons $
- *
- */
-
-
- /**************************************************************************
- * *
- * Section: Macros, Definitions, Includes, Structures *
- * *
- **************************************************************************/
-
- /************************************* Includes ***********/
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <string.h>
- #include <ctype.h>
-
- #include <exec/execbase.h>
-
- #include "pgpsendmail.h" /* standard defines */
- #include "protos.h" /* protoypes of all available routines */
-
- #include "pgpsendmail_rev.h" /* bumprevision stuff (AmigaOS only) */
-
- /************************************* Prototypes *********/
- void my_exit(void);
- void sendmail(void);
-
- /************************************* Defines ************/
- #define PGP "PGP -fesa <%s >%s %s +batchmode"
- #define PGPKEYLIST "UULib:PGPKeys.lst"
-
- #define BODY_ID "Automatically encrypted message-body follows:\n\n"
-
- /************************************* global Variables ***/
- static const char __OSVer[] = VERSTAG;
- static const char __RCSId[] = "$Id: pgpsendmail.c,v 1.45 1994/03/21 14:54:52 simons Exp simons $";
- char PRGNAME[] = "PGPSendmail";
-
- struct NetSupportLibrary *NetSupportBase;
- FILE *mailfh, *tmpfh;
- char mailfilename[L_tmpnam], tmpfilename[L_tmpnam], encryptedfilename[L_tmpnam], *argline, *tmpbuf;
- int exitPipe = 1;
-
- /**************************************************************************
- * *
- * Section: main program *
- * *
- **************************************************************************/
-
- int main(int argc, char **argv)
- {
- extern struct ExecBase *SysBase;
- BPTR pipe, tmp_pipe;
- char **receipients, *cmdbuf, *header, *tmp, *ptr;
- int rc;
-
-
- /*
- * Initialize the requires resources and return if something fails!
- */
-
- if (SysBase->LibNode.lib_Version < 37) {
- fprintf(stderr, "%s: Kickstart 2.04 or later is required!", PRGNAME);
- return 20;
- }
- if (atexit(my_exit)) {
- fprintf(stderr, "%s: Could not install my exit handler!\n", PRGNAME);
- return 20;
- }
- if (!(NetSupportBase = (struct NetSupportLibrary *) OpenLibrary("netsupport.library", 0L))) {
- fprintf(stderr, "%s: Failed opening NetSupport.Library!", PRGNAME);
- return 20;
- }
- if (!(cmdbuf = malloc(MAX_CMDLINELEN)) || (!(tmpbuf = malloc(MY_BUFLEN)))) {
- MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Failed allocating my buffers!");
- return 20;
- }
- tmpnam(mailfilename);
- tmpnam(tmpfilename);
- tmpnam(encryptedfilename);
- argline = GetOriginalCmdLine(argc, argv); /* Re-build the original commandline, because
- * the real sendmail will need it later.
- */
-
- /*
- * Copy standard input to a temporary file for security reasons.
- */
-
- if (!(mailfh = fopen(mailfilename, "w"))) {
- MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Failed opening %s!", mailfilename);
- return 20;
- }
- while (fgets(tmpbuf, MY_BUFLEN, stdin)) {
- if (fputs(tmpbuf, mailfh) == EOF) {
- MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Can't write to %s!", mailfilename);
- return 20;
- }
- }
- fclose(mailfh); mailfh = NULL;
- MakeLogEntry(PRGNAME, MLE_DEBUG2, "original mail is now in '%s'.", mailfilename);
-
-
- /*
- * Now that the mail is safe, install an exit handler that pipes the
- * file to sendmail when we exit, to make sure the mail will not be
- * lost under error condition.
- */
-
- if (atexit(sendmail)) {
- fprintf(stderr, "%s: Could not install my exit handler!\n", PRGNAME);
- return 20;
- }
-
-
-
- /*
- * Load the mail header for RFC routines.
- */
-
- if (!(header = malloc(10*1024))) { /* allocate 10k for the mail header */
- MakeLogEntry(PRGNAME, MLE_ERROR, "Failed allocating my buffers!");
- return 10;
- }
- if (!(mailfh = fopen(mailfilename, "r"))) {
- MakeLogEntry(PRGNAME, MLE_ERROR, "Failed opening %s!", mailfilename);
- return 10;
- }
- tmp = header;
- while (fgets(tmp, MY_BUFLEN, mailfh)) {
- if (strlen(tmp) == 1) /* Have we reached the mail body? */
- break;
- tmp += strlen(tmp);
- }
-
-
-
- /*
- * Determine receipients to decide whom to encrypt to.
- */
-
- receipients = FindReceipients(header);
- free(header); /* Header isn't needed anymore. */
-
- if (!receipients || (!*receipients)) {
- MakeLogEntry(PRGNAME, MLE_ERROR, "Can't determine receipient of message.");
- return 10;
- }
- else
- MakeLogEntry(PRGNAME, MLE_DEBUG2, "receipients (including aliases): %s", ArrayToLine(receipients));
- receipients = ExpandAliases(receipients);
- if (!receipients || (!*receipients)) {
- MakeLogEntry(PRGNAME, MLE_ERROR, "Can't determine receipient of message.");
- return 10;
- }
- else
- MakeLogEntry(PRGNAME, MLE_DEBUG2, "receipients (aliases expanded): %s", ArrayToLine(receipients));
- MakeDomainAddress(receipients);
-
-
-
- /*
- * Check wether all keys are available or not.
- */
-
- if ((CheckKeyAvailability(receipients)) == 0) {
- MakeLogEntry(PRGNAME, MLE_DEBUG2, "Not all receipients have a valid public key.");
- return 0;
- }
-
-
-
- /*
- * Ask user wether this mail should be encrypted or not.
- */
-
- ptr = GetConfig(NULL, CONFIRMENCRYPTION, NULL, "y");
- if (ptr[0] == 'y' || ptr[0] == 'Y')
- if (!ConfirmEncryption()) {
- MakeLogEntry(PRGNAME, MLE_INFO, "Encryption denied by user.");
- return 0;
- }
-
-
- /*
- * Copy messagebody for encryption.
- */
-
- if (!(tmpfh = fopen(tmpfilename, "w"))) {
- MakeLogEntry(PRGNAME, MLE_ERROR, "Failed opening %s!", tmpfilename);
- return 5;
- }
- while (fgets(tmpbuf, MY_BUFLEN, mailfh)) { /* The fileposition is at the begin of the
- * mailbody because we read the header earlier.
- */
- if (fputs(tmpbuf, tmpfh) == EOF) {
- MakeLogEntry(PRGNAME, MLE_ERROR, "Can't write to %s!", tmpfilename);
- return 5;
- }
- }
- fclose(mailfh); mailfh = NULL;
- fclose(tmpfh); tmpfh = NULL;
-
-
-
- /*
- * Encrypt message body.
- */
-
- sprintf(tmpbuf, "PGP -ftea <%s >%s %s", tmpfilename, encryptedfilename, ArrayToLine(receipients));
- MakeLogEntry(PRGNAME, MLE_DEBUG1, "calling '%s'", tmpbuf);
- if (rc = system(tmpbuf)) {
- MakeLogEntry(PRGNAME, MLE_ERROR, "PGP returned error code %ld", rc);
- return 5;
- }
- else
- MakeLogEntry(PRGNAME, MLE_INFO, "succesfully encrypted the mail for %s", ArrayToLine(receipients));
-
- remove(tmpfilename); /* isn't required anymore */
-
-
-
- /*
- * Call SendMail to handle the message.
- */
-
- sprintf(tmpbuf, "%s %s", FindConfig(SENDMAIL), argline);
- MakeLogEntry(PRGNAME, MLE_DEBUG1, "Calling '%s'", tmpbuf);
-
- /*
- * PORT NOTE: Sorry, but I need POpen() again. To make this stuff work on
- * another platform, you'll have to re-write it completely.
- */
-
- if (pipe = POpen(tmpbuf, MODE_PIPETO)) {
-
-
- /* Pipe the mail header to sendmail. */
-
- if (tmp_pipe = Open(mailfilename, MODE_OLDFILE)) {
- while (FGets(tmp_pipe, tmpbuf, MY_BUFLEN)) {
- FPuts(pipe, tmpbuf);
- if (strlen(tmpbuf) == 1) /* header is copied completely */
- break;
- }
- Close(tmp_pipe);
-
-
- /* Pipe the encrypted mail body to sendmail. */
-
- FPuts(pipe, BODY_ID);
- if (tmp_pipe = Open(encryptedfilename, MODE_OLDFILE)) {
- while (FGets(tmp_pipe, tmpbuf, MY_BUFLEN))
- FPuts(pipe, tmpbuf);
- Close(tmp_pipe);
- }
-
- exitPipe = 0; /* The mail is sent already, we don't need the sendmail()
- * exit handler anymore.
- */
- }
-
- rc = PClose(pipe);
- }
- else {
- MakeLogEntry(PRGNAME, MLE_ERROR, "Can't send the encrypted mail!");
- return 5;
- }
-
- return rc;
- }
-
-
- /**************************************************************************
- * *
- * SECTION: Subroutines *
- * *
- **************************************************************************/
-
- /*
- * This exit handler will free all resources allocated by the program
- * when we exit to make sure nothing is wasted under error condition.
- *
- * PORT NOTE: Contains system-dependant stuff!
- */
-
- void my_exit(void)
- {
- /* Close all open files and delete them afterwards. */
-
- if (mailfh)
- fclose(mailfh);
- if (tmpfh)
- fclose(tmpfh);
-
- remove(mailfilename);
- remove(tmpfilename);
- remove(encryptedfilename);
-
-
- /* Free all locked files and close the netsupport.library. */
-
- if (NetSupportBase) {
- UnLockFiles();
- CloseLibrary((struct Library *) NetSupportBase);
- }
- }
-
-
- /*
- * Pipe the mailfile to sendmail when we exit.
- *
- * PORT NOTE: Because the AmigaOS doen't know popen(), we have to use
- * the routine from the netsupport.library. For other operating systems
- * it will be necessary to replace the whole routine!
- */
-
- void sendmail(void)
- {
- BPTR pipe, fh;
- int len;
-
- if (!exitPipe)
- return;
-
- sprintf(tmpbuf, "%s %s", FindConfig(SENDMAIL), argline);
- MakeLogEntry(PRGNAME, MLE_DEBUG1, "Calling '%s'", tmpbuf);
- if (pipe = POpen(tmpbuf, MODE_PIPETO)) {
-
- /* If the file holding the mail is still open, close it first
- * to make sure we can access it.
- */
-
- if (mailfh) {
- fclose(mailfh); mailfh = NULL;
- }
-
- /* Pipe the whole file to sendmail. */
-
- if (fh = Open(mailfilename, MODE_OLDFILE)) {
- while (len = Read(fh, tmpbuf, MY_BUFLEN-1)) {
- if (len == -1L)
- break; /* Read() failed */
- if (Write(pipe, tmpbuf, len) == -1L)
- break; /* Write() failed */
- }
- Close(fh);
- }
- else
- MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Couldn't open mailfile! Mail is lost!!");
- PClose(pipe);
- }
- else
- MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Couldn't open pipe to sendmail! Mail is lost!!");
- }
-
-
-
- char *ArrayToLine(char *array[])
- {
- char *line;
-
- if (!(line = malloc(MY_BUFLEN)))
- return NULL;
- line[0] = '\0';
-
- while (*array != NULL) {
- strcat(line, *array);
- strcat(line, " ");
- array++;
- }
- return line;
- }
-
-
- int CheckKeyAvailability(char *receipients[])
- {
- FILE *fh;
- char *keylist;
- int filelength;
-
- if (*receipients == NULL)
- return 0; /* No receipient found! */
-
- LockFile(PGPKEYLIST);
-
- if ((fh = fopen(PGPKEYLIST, "r")) == NULL) {
- UnLockFile(PGPKEYLIST);
- return 0; /* Couldn't open keylist! */
- }
- fseek(fh, 0L, SEEK_END); filelength = ftell(fh);
- /* Determine filelength. */
-
-
- /* Allocate buffer and read keylist. */
-
- if (keylist = malloc(filelength+1)) {
- lseek(fileno(fh), 0, 0);
- if ((read(fileno(fh), keylist, filelength)) == -1) {
- fclose(fh); /* Couldn't read keylist. */
- UnLockFile(PGPKEYLIST);
- free(keylist);
- return 0;
- }
- else { /* Read went fine. */
- fclose(fh);
- UnLockFile(PGPKEYLIST);
- keylist[filelength] = '\0';
-
- while (*receipients != NULL) {
- if (FindKey(*receipients, keylist) == 0) {
- free(keylist);
- MakeLogEntry(PRGNAME, MLE_DEBUG1, "No key available for <%s>.", *receipients);
- return 0; /* Key is not in keylist. */
- }
- receipients++;
- }
- }
- }
- free(keylist);
- return 1; /* Everything is fine. */
- }
-
- int FindKey(char *key, char *keylist)
- {
- char line[MY_BUFLEN];
- int i;
-
- while (*keylist != '\0') {
-
- /* Is this a valid key-line? */
-
- if (!strnicmp(keylist, "pub ", strlen("pub "))
- || !strnicmp(keylist, " ", strlen(" ")))
- {
- for(i = 0; keylist[i] != '\n'; i++)
- line[i] = keylist[i];
- line[i] = '\0';
- if (stristr(line, key))
- return 1;
- }
-
-
- /* Find end of line or end of buffer. */
-
- while (*keylist != '\n' && *keylist != '\0')
- keylist++;
- keylist++;
- }
- return 0;
- }
-
- char *stristr(char *line, char *key)
- {
- int i, cmplen = strlen(key), end = strlen(line)-cmplen;
-
- for (i = 0; i <= end; i++)
- if (strnicmp(&line[i], key, cmplen) == NULL)
- return &line[i];
- return NULL;
- }
-
-