Index: ossp-pkg/petidomo/filter.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/filter.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/filter.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/filter.c' 2>/dev/null --- ossp-pkg/petidomo/filter.c +++ - 2024-05-10 12:04:45.999102989 +0200 @@ -0,0 +1,230 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define READ 0 +#define WRITE 1 +#define IO_BLOCKSIZE (4*1024) + +enum { + STATE_HEADER, + STATE_SEPERATOR, + STATE_BODY, + STATE_FINISHED +}; + +int +MailFilter(struct Mail * MailStruct, const char * filter) +{ + int child_in[2]; + int child_out[2]; + pid_t child_pid; + int rc, i; + int write_state; + int byte_read, byte_written; + char * newmail = NULL; + int newmail_size = 0; + char * p = NULL; + + assert(MailStruct != NULL); + assert(filter != NULL); + + debug((DEBUG_FILTER, 2, "Starting mail filter \"%s\".", filter)); + + /* Sanity checks. */ + + if (MailStruct == NULL || filter == NULL) + return 0; + + /* Init pipes. */ + + if (pipe(child_in) == -1) { + syslog(LOG_ERR, "Couldn't open a writing-pipe to my child process: %m"); + return -1; + } + if (pipe(child_out) == -1) { + syslog(LOG_ERR, "Couldn't open a read-pipe from my child process: %m"); + return -1; + } + + /* Fork. */ + + child_pid = fork(); + switch(child_pid) { + case 0: + /* Child */ + close(child_in[WRITE]); + close(child_out[READ]); + if (dup2(child_in[READ], STDIN_FILENO) == -1) { + syslog(LOG_ERR, "Child process couldn't read from pipe: %m"); + return -1; + } + if (dup2(child_out[WRITE], STDOUT_FILENO) == -1) { + syslog(LOG_ERR, "Child process couldn't read from pipe: %m"); + return -1; + } + close(child_in[READ]); + close(child_out[WRITE]); + debug((DEBUG_FILTER, 2, "Child process is set up. Executing filter.")); + execl("/bin/sh", "sh", "-c", filter, NULL); + return -1; + case -1: + /* Error */ + close(child_in[READ]); + close(child_in[WRITE]); + close(child_out[READ]); + close(child_out[WRITE]); + syslog(LOG_ERR, "Couldn't fork: %m"); + return -1; + default: + /* everything is fine */ + close(child_in[READ]); + close(child_out[WRITE]); + } + + /* Switch the pipes into non-blocking mode. */ + + rc = fcntl(child_in[WRITE], F_GETFL, 0); + if (rc == -1) { + syslog(LOG_ERR, "Couldn't get flags from write-pipe descriptor: %m"); + goto error_exit; + } + rc |= O_NONBLOCK; + rc = fcntl(child_in[WRITE], F_SETFL, rc); + if (rc == -1) { + syslog(LOG_ERR, "Couldn't set flags for write-pipe descriptor: %m"); + goto error_exit; + } + rc = fcntl(child_out[READ], F_GETFL, 0); + if (rc == -1) { + syslog(LOG_ERR, "Couldn't get flags from write-pipe descriptor: %m"); + goto error_exit; + } + rc |= O_NONBLOCK; + rc = fcntl(child_out[READ], F_SETFL, rc); + if (rc == -1) { + syslog(LOG_ERR, "Couldn't set flags for write-pipe descriptor: %m"); + goto error_exit; + } + debug((DEBUG_FILTER, 4, "Pipes are in non-blocking mode now.")); + + /* Now write the mail into the pipe and read the result from the + child. This has to happen parallely or we risk that the child + hangs with a blocking i/o. */ + + write_state = STATE_HEADER; + byte_read = 0; + byte_written = 0; + + for (;;) { + /* Write to the pipe. */ + + switch (write_state) { + case STATE_HEADER: + p = MailStruct->Header; + break; + case STATE_SEPERATOR: + p = "\n"; + break; + case STATE_BODY: + p = MailStruct->Body; + break; + case STATE_FINISHED: + p = NULL; + break; + } + if (p != NULL) { + rc = write(child_in[WRITE], p + byte_written, + (strlen(p + byte_written) > IO_BLOCKSIZE) ? + IO_BLOCKSIZE : strlen(p + byte_written)); + debug((DEBUG_FILTER, 4, "Write returned '%d'.", rc)); + if (rc >= 0) { + byte_written += rc; + if (p[byte_written] == '\0') { + debug((DEBUG_FILTER, 2, "New write state")); + write_state++; /* new state */ + byte_written = 0; + if (write_state == STATE_FINISHED) + close(child_in[WRITE]); + } + } + else if (errno != EAGAIN) { + syslog(LOG_ERR, "Writing to the filter process failed: %m"); + goto error_exit; + } + } + + /* Read from the pipe. */ + + if ((newmail_size - byte_read) <= (IO_BLOCKSIZE)) { + newmail_size += 10*1024; + debug((DEBUG_FILTER, 4, "Allocting new read buffer: %d byte", newmail_size)); + newmail = realloc(newmail, newmail_size); + if (newmail == NULL) { + syslog(LOG_ERR, "Failed to allocate %d byte of memory: %m", newmail_size); + goto error_exit; + } + } + rc = read(child_out[READ], newmail + byte_read, IO_BLOCKSIZE); + debug((DEBUG_FILTER, 4, "Read returned '%d'.", rc)); + if (rc > 0) + byte_read += rc; + else if (rc == 0) { + close(child_out[READ]); + break; /* we are finished */ + } + else if (errno != EAGAIN) { + syslog(LOG_ERR, "Reading from filter process failed: %m"); + goto error_exit; + } + else { + debug((DEBUG_FILTER, 4, "read would block")); + } + } + newmail[byte_read] = '\0'; + + /* Parse mail and put it into the structure. */ + + for (i = 0; newmail[i] != '\0'; i++) { + if (i > 0 && newmail[i-1] == '\n' && newmail[i] == '\n') { + free(MailStruct->Header); + MailStruct->Header = newmail; + newmail[i] = '\0'; + MailStruct->Body = newmail+i+1; + break; + } + } + debug((DEBUG_FILTER, 5, "New header is:\n%s", MailStruct->Header)); + debug((DEBUG_FILTER, 5, "New body is:\n%s", MailStruct->Body)); + + /* Get returncode. */ + + waitpid(child_pid, &rc, 0); + if (!WIFEXITED(rc)) + return -1; + + debug((DEBUG_FILTER, 4, "Filter \"%s\" returned %d.", filter, WEXITSTATUS(rc))); + return WEXITSTATUS(rc); + + return 0; + +error_exit: + close(child_in[WRITE]); + close(child_out[READ]); + kill(child_pid, SIGTERM); + return -1; +} Index: ossp-pkg/petidomo/handleacl.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/handleacl.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/handleacl.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/handleacl.c' 2>/dev/null --- ossp-pkg/petidomo/handleacl.c +++ - 2024-05-10 12:04:46.001939152 +0200 @@ -0,0 +1,151 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include + +#include + +/* Returncodes have the following meaning: '-1' == Error, '0' == + Proceed, '1' == Mail has been taken care of. */ + +int +handleACL(struct Mail * MailStruct, const char * listname, int operation, char * parameter) +{ + const struct PD_Config * MasterConfig; + const struct List_Config * ListConfig; + FILE * fh; + char * buffer; + char envelope[1024]; + char owner[1024]; + int rc; + + assert(MailStruct != NULL); + + MasterConfig = getMasterConfig(); + if (listname != NULL) { + ListConfig = getListConfig(listname); + sprintf(envelope, "%s-owner@%s", listname, ListConfig->fqdn); + sprintf(owner, "%s-owner@%s", listname, ListConfig->fqdn); + } + else { + sprintf(envelope, "petidomo-manager@%s", MasterConfig->fqdn); + sprintf(owner, "petidomo-manager@%s", MasterConfig->fqdn); + } + + /* Check for authorization. */ + + switch(operation) { + case ACL_NONE: + debug((DEBUG_ACL, 4, "No ACL statement matched the mail.")); + break; + case ACL_PASS: + debug((DEBUG_ACL, 4, "Mail passed access control.")); + break; + case ACL_DROP: + syslog(LOG_INFO, "Mail is dropped due to access control."); + return 1; + case ACL_REJECTWITH: + assert(parameter != NULL); + case ACL_REJECT: + syslog(LOG_INFO, "Mail is rejected due to access control."); + fh = vOpenMailer(envelope, owner, (MailStruct->Reply_To) ? + (MailStruct->Reply_To) : (MailStruct->From), NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to open mailer for redirection."); + return -1; + } + fprintf(fh, "From: %s (Petidomo Mailing List Server)\n", owner); + fprintf(fh, "To: %s\n", (MailStruct->Reply_To) ? + (MailStruct->Reply_To) : (MailStruct->From)); + fprintf(fh, "Cc: %s\n", owner); + if (listname != NULL) + fprintf(fh, "Subject: Your posting to list \"%s\" was rejected\n", listname); + else + fprintf(fh, "Subject: Your petidomo request was rejected\n"); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", owner); + fprintf(fh, "\n"); + if (operation == ACL_REJECTWITH && (buffer = loadfile(parameter)) != NULL) { + fprintf(fh, "%s\n", buffer); + free(buffer); + } + else + fprintf(fh, "Your article was rejected by the access control rules:\n\n"); + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s", MailStruct->Body); + CloseMailer(fh); + return 1; + case ACL_REDIRECT: + assert(parameter != NULL); + syslog(LOG_INFO, "Mail is redirected to \"%s\" due to access control.", parameter); + fh = vOpenMailer(MailStruct->Envelope, parameter, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to open mailer for redirection."); + return -1; + } + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s", MailStruct->Body); + CloseMailer(fh); + return 1; + case ACL_FORWARD: + assert(parameter != NULL); + syslog(LOG_INFO, "Mail is forwarded to \"%s\" due to access control.", parameter); + fh = vOpenMailer(envelope, parameter, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to open mailer for redirection."); + return -1; + } + fprintf(fh, "From: %s (Petidomo Mailing List Server)\n", owner); + fprintf(fh, "To: %s\n", parameter); + if (listname != NULL) + fprintf(fh, "Subject: Disallowed posting from \"%s\" to list \"%s\"\n", + MailStruct->From, listname); + else + fprintf(fh, "Subject: Disallowed petidomo request from \"%s\"\n", + MailStruct->From); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", owner); + fprintf(fh, "\n"); + fprintf(fh, "The following article was forwarded to you, due to the\n" \ + "access control rules:\n\n"); + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s", MailStruct->Body); + CloseMailer(fh); + return 1; + case ACL_FILTER: + assert(parameter != NULL); + syslog(LOG_INFO, "Mail is filtered through \"%s\" due to access control.", + parameter); + rc = MailFilter(MailStruct, parameter); + debug((DEBUG_ACL, 3, "Mail filter \"%s\" returned %d.", parameter, rc)); + if (rc != 0) { + syslog(LOG_ERR, "Mail filter \"%s\" returned error code %d.", parameter, rc); + return -1; + } + break; + default: + syslog(LOG_CRIT, "Internal error: Unexpected return code %d from checkACL()", + operation); + return -1; + } + if (parameter != NULL) + free(parameter); + +#ifdef DEBUG + if (listname != NULL) { + debug((DEBUG_ACL, 3, "\"%s\" is authorized to post to \"%s\".", + MailStruct->From, listname)); + } + else { + debug((DEBUG_ACL, 3, "Request from \"%s\" is okay, says ACL", MailStruct->From)); + } +#endif + + return 0; +} Index: ossp-pkg/petidomo/help.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/help.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/help.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/help.c' 2>/dev/null --- ossp-pkg/petidomo/help.c +++ - 2024-05-10 12:04:46.005166524 +0200 @@ -0,0 +1,206 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include + +int +SendHelp(struct Mail * MailStruct, + const char * param1, + const char * param2, + const char * defaultlist) +{ + const struct PD_Config * MasterConfig; + const struct List_Config * ListConfig = NULL; + FILE * fh; + char * originator; + char * p; + char envelope[1024]; + char * buffer; + + /* Find out who is who and what to send. */ + + MasterConfig = getMasterConfig(); + if (defaultlist != NULL) { + ListConfig = getListConfig(defaultlist); + sprintf(envelope, "%s-owner@%s", defaultlist, ListConfig->fqdn); + } + else + sprintf(envelope, "petidomo-manager@%s", MasterConfig->fqdn); + originator = (MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From; + if (param1 != NULL) { + if (isValidListName(param1) == TRUE) { + + /* Send list's description back. */ + + debug((DEBUG_COMMAND, 5, "Sending \"%s\" list \"%s\" description.", + originator, param1)); + ListConfig = getListConfig(param1); + sprintf(envelope, "%s-owner@%s", param1, MasterConfig->fqdn); + fh = vOpenMailer(envelope, originator, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to send mail to \"%s\" regarding this request.", + originator); + return -1; + } + fprintf(fh, "From: %s-request@%s (Petidomo Mailing List Server)\n", + param1, ListConfig->fqdn); + fprintf(fh, "To: %s\n", originator); + fprintf(fh, "Subject: Your request \"help %s\"\n", param1); + if (MailStruct->Message_Id != NULL) + fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", envelope); + fprintf(fh, "\n"); + fprintf(fh, "Description of list \"%s\":\n\n", param1); + buffer = text_easy_sprintf("lists/%s/description", param1); + p = loadfile(buffer); + if (p != NULL) { + fprintf(fh, "%s\n", p); + free(p); + } + else { + syslog(LOG_NOTICE, "List \"%s\" doesn't have a description.", param1); + fprintf(fh, "No description available.\n"); + } + AppendSignature(fh); + CloseMailer(fh); + } + else { + + /* List does not exist, I am afraid. */ + + debug((DEBUG_COMMAND, 5, "Received HELP command for non-existing list \"%s\".", + param1)); + fh = vOpenMailer(envelope, originator, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to send mail to \"%s\" regarding this request.", + originator); + return -1; + } + if (defaultlist != NULL) + fprintf(fh, "From: %s-request@%s (Petidomo Mailing List Server)\n", + defaultlist, ListConfig->fqdn); + else + fprintf(fh, "From: petidomo@%s (Petidomo Mailing List Server)\n", + MasterConfig->fqdn); + fprintf(fh, "To: %s\n", originator); + fprintf(fh, "Subject: Your request \"help %s\"\n", param1); + if (MailStruct->Message_Id != NULL) + fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", envelope); + fprintf(fh, "\n"); + buffer = text_easy_sprintf( +"There is no mailing list \"%s\" on this machine, I am afraid. Please check " \ +"whether you spelled the name of the list correctly, or whether you have been " \ +"sending this request to the wrong address.\n\nYou can receive a list of all " \ +"mailing lists available here by sending the command \"INDEX\" to the " \ +"mailing list server.", param1); + text_wordwrap(buffer, 75); + fprintf(fh, "%s\n", buffer); + AppendSignature(fh); + CloseMailer(fh); + } + } + else { + + /* Send help text to the originator. */ + + debug((DEBUG_COMMAND, 5, "Sending helpfile to \"%s\".", originator)); + fh = vOpenMailer(envelope, originator, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to send mail to \"%s\" regarding this request.", + originator); + return -1; + } + if (defaultlist != NULL) + fprintf(fh, "From: %s-request@%s (Petidomo Mailing List Server)\n", + defaultlist, ListConfig->fqdn); + else + fprintf(fh, "From: petidomo@%s (Petidomo Mailing List Server)\n", + MasterConfig->fqdn); + fprintf(fh, "To: %s\n", originator); + fprintf(fh, "Subject: Your request \"help\"\n"); + if (MailStruct->Message_Id != NULL) + fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", envelope); + fprintf(fh, "\n"); + p = loadfile("etc/help"); + if (p != NULL) { + fprintf(fh, "%s\n", p); + free(p); + } + else { + syslog(LOG_ERR, "There is no help file for Petidomo!"); + fprintf(fh, "No help text available.\n"); + } + AppendSignature(fh); + CloseMailer(fh); + } + + return 0; +} + +int +Indecipherable(struct Mail * MailStruct, const char * defaultlist) +{ + const struct PD_Config * MasterConfig; + const struct List_Config * ListConfig = NULL; + FILE * fh; + char * replyto; + char * p; + char envelope[1024]; + + /* Find out who is who and what to send. */ + + MasterConfig = getMasterConfig(); + if (defaultlist != NULL) { + ListConfig = getListConfig(defaultlist); + sprintf(envelope, "%s-owner@%s", defaultlist, ListConfig->fqdn); + } + else + sprintf(envelope, "petidomo-manager@%s", MasterConfig->fqdn); + replyto = (MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From; + + /* Send the help file out. */ + + debug((DEBUG_COMMAND, 5, "Sending helpfile to \"%s\".", replyto)); + fh = vOpenMailer(envelope, replyto, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to send mail to \"%s\" regarding this request.", replyto); + return -1; + } + if (defaultlist != NULL) + fprintf(fh, "From: %s-request@%s (Petidomo Mailing List Server)\n", + defaultlist, ListConfig->fqdn); + else + fprintf(fh, "From: petidomo@%s (Petidomo Mailing List Server)\n", + MasterConfig->fqdn); + fprintf(fh, "To: %s\n", replyto); + fprintf(fh, "Subject: Your request \"indecipherable\"\n"); + if (MailStruct->Message_Id != NULL) + fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", envelope); + fprintf(fh, "\n"); + p = loadfile("etc/help"); + if (p != NULL) { + fprintf(fh, "%s\n", p); + free(p); + } + else { + syslog(LOG_ERR, "There is no help file for Petidomo!"); + fprintf(fh, "No help text available.\n"); + } + AppendSignature(fh); + CloseMailer(fh); + return 0; +} Index: ossp-pkg/petidomo/hermes.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/hermes.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/hermes.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/hermes.c' 2>/dev/null --- ossp-pkg/petidomo/hermes.c +++ - 2024-05-10 12:04:46.007921012 +0200 @@ -0,0 +1,292 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include + +#include +#include + +int +hermes_main(char * incoming_mail, const char * listname) +{ + const struct PD_Config * MasterConfig; + const struct List_Config * ListConfig; + struct stat sb; + struct Mail * MailStruct; + FILE * fh; + char * PostingHeaders; + char * currLine; + char * nextLine; + char * dst; + char * parameter; + char * buffer; + char envelope[1024]; + char owner[1024]; + int rc, len, operation; + + assert(listname != NULL); + debug((DEBUG_HERMES, 5, "Received article for the \"%s\" mailing list", listname)); + + /* Initialize internals. */ + + ListConfig = getListConfig(listname); + + /* Parse the incoming mail. */ + + rc = ParseMail(&MailStruct, incoming_mail, ListConfig->fqdn); + if (rc != 0) { + syslog(LOG_ERR, "Parsing the incoming mail failed."); + exit(rc); + } + + debug((DEBUG_HERMES, 3, "Parsed incoming mail successfully.")); + + /* Do sanity checks. */ + + if (MailStruct->From == NULL) { + syslog(LOG_NOTICE, "Received mail without From: line."); + return 0; + } + if (*MailStruct->Body == '\0') { + syslog(LOG_NOTICE, "Received mail with empty body."); + return 0; + } + + /* Initialize internal stuff. */ + + if (isValidListName(listname) == FALSE) { + syslog(LOG_ERR, "Mailing list \"%s\" does not exist.", listname); + exit(1); + } + PostingHeaders = xmalloc(strlen(MailStruct->Header)+1024); + MasterConfig = getMasterConfig(); + sprintf(envelope, "%s-owner@%s", listname, ListConfig->fqdn); + sprintf(owner, "%s-owner@%s", listname, ListConfig->fqdn); + + /* Check for authorization. */ + + debug((DEBUG_HERMES, 5, "Checking whether posting is authorized.")); + + if (FindBodyPassword(MailStruct) != 0) + exit(1); + + if (isValidPostingPassword(MailStruct->Approve, listname) == FALSE) { + + /* No valid password found. Reject the article, if the list is + of type 'moderated'. */ + + if (ListConfig->listtype == LIST_MODERATED) { + syslog(LOG_NOTICE, "\"%s\" tried to post to list \"%s\", but failed to " \ + "provide a correct password.", MailStruct->From, listname); + + fh = vOpenMailer(envelope, owner, NULL); + if (fh != NULL) { + fprintf(fh, "From: %s (Petidomo Mailing List Server)\n", owner); + fprintf(fh, "To: %s\n", owner); + fprintf(fh, "Subject: Unauthorized posting to list \"%s\"\n", listname); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", owner); + fprintf(fh, "\n"); + fprintf(fh, "The following article was rejected:\n\n"); + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s", MailStruct->Body); + CloseMailer(fh); + } + else { + syslog(LOG_ERR, "Failed to send email to \"%s\" concerning this request.", + owner); + return -1; + } + return 0; + } + + if (ListConfig->listtype == LIST_CLOSED) { + /* Only subscribers may post */ + if (isSubscribed(listname, MailStruct->From, NULL, NULL, TRUE) == FALSE) { + debug((DEBUG_HERMES, 5, "\"%s\" is not a subscriber of \"%s\". Rejecting.", + MailStruct->From, listname)); + + fh = vOpenMailer(envelope, owner, NULL); + if (fh != NULL) { + fprintf(fh, "From: %s (Petidomo Mailing List Server)\n", owner); + fprintf(fh, "To: %s\n", owner); + fprintf(fh, "Subject: Unauthorized posting to list \"%s\"\n", listname); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", owner); + fprintf(fh, "\n"); + fprintf(fh, "The following article was rejected, because the sender\n" \ + "\"%s\" is not subscribed to the list:\n\n", MailStruct->From); + fprintf(fh, "%s\n", MailStruct->Header); + fprintf(fh, "%s", MailStruct->Body); + CloseMailer(fh); + } + else { + syslog(LOG_ERR, "Failed to send email to \"%s\" concerning this request.", + owner); + return -1; + } + return 0; + } + } + + if (checkACL(MailStruct, listname, &operation, ¶meter) != 0) { + syslog(LOG_ERR, "checkACL() failed with an error."); + exit(1); + } + rc = handleACL(MailStruct, listname, operation, parameter); + debug((DEBUG_HERMES, 8, "handleACL() returned %d.", rc)); + switch(rc) { + case -1: + syslog(LOG_ERR, "handleACL() failed with an error."); + exit(1); + case 0: + break; + case 1: + return 0; + } + + debug((DEBUG_HERMES, 3, "\"%s\" is authorized to post to \"%s\".", + MailStruct->From, listname)); + } + else { + debug((DEBUG_HERMES, 5, "Listtype doesn't require authorization.")); + } + + /* Copy the desired headers from the original mail to our own + buffer. */ + + debug((DEBUG_HERMES, 9, "Preparing headers for posting.")); + for(len = 0, currLine = MailStruct->Header, dst = PostingHeaders; + *currLine != '\0'; + currLine = nextLine) { + + /* Find next header line. */ + + nextLine = text_find_next_line(currLine); + while (*nextLine == '\t' || *nextLine == ' ') + nextLine = text_find_next_line(nextLine); + + /* Copy the current line into our own buffer. */ + + if (!strncasecmp(currLine, "From:", 5) || + !strncasecmp(currLine, "To:", 3) || + !strncasecmp(currLine, "Cc:", 3) || + !strncasecmp(currLine, "Subject:", 8) || + !strncasecmp(currLine, "Date:", 5) || + !strncasecmp(currLine, "MIME-Version:", 13) || + !strncasecmp(currLine, "Content-Type:", 13) || + !strncasecmp(currLine, "Content-Transfer-Encoding:", 26) || + !strncasecmp(currLine, "In-Reply-To:", 12) || + !strncasecmp(currLine, "References:", 11) || + !strncasecmp(currLine, "Message-Id:", 11) || + !strncasecmp(currLine, "Received:", 9)) { + len = nextLine - currLine; + memmove(dst, currLine, len); + dst += len; + debug((DEBUG_HERMES, 9, "Copied line.")); + } + } + + /* Add a Reply-To: field. */ + + if (ListConfig->reply_to == NULL) + len = sprintf(dst, "Reply-To: %s@%s\n", listname, ListConfig->fqdn); + else if (!strcasecmp(ListConfig->reply_to, "none")) { + if (MailStruct->Reply_To != NULL) { + + /* Copy Reply-To: line from original header. */ + + for(len = 0, currLine = MailStruct->Header; + *currLine != '\0'; + currLine = nextLine) { + + nextLine = text_find_next_line(currLine); + while (*nextLine == '\t' || *nextLine == ' ') + nextLine = text_find_next_line(nextLine); + + if (!strncasecmp(currLine, "Reply-To:", 9)) { + len = nextLine - currLine; + memmove(dst, currLine, len); + } + } + + } + else + len = 0; + } + else { + len = sprintf(dst, "Reply-To: %s\n", ListConfig->reply_to); + } + dst += len; + + /* Add a Sender: field. */ + + len = sprintf(dst, "Sender: %s\n", owner); + dst += len; + + /* Add a Precedence: field. */ + + len = sprintf(dst, "Precedence: list\n"); + dst += len; + *dst = '\0'; + + /* Add the signature if there is one. */ + + buffer = text_easy_sprintf("lists/%s/signature", listname); + debug((DEBUG_HERMES, 6, "Checking whether \"%s\" exists.", buffer)); + if (stat(buffer, &sb) == 0) { + debug((DEBUG_HERMES, 3, "Appending signature \"%s\".", buffer)); + buffer = loadfile(buffer); + if (buffer == NULL) { + syslog(LOG_ERR, "Failed reading the signature file for list \"%s\".", listname); + exit(1); + } + MailStruct->ListSignature = buffer; + debug((DEBUG_HERMES, 7, "Signature is: \"%s\".", buffer)); + } + else + debug((DEBUG_HERMES, 3, "No signature file \"%s\".", buffer)); + + /* No more modifications will be made. Now copy the posting + headers into the structure instead of the original ones. */ + + MailStruct->Header = PostingHeaders; + + /* Apply the posting filter. */ + + if (ListConfig->postingfilter != NULL) { + debug((DEBUG_HERMES, 3, "Applying posting filter for list \"%s\".", listname)); + rc = MailFilter(MailStruct, ListConfig->postingfilter); + if (rc != 0) { + syslog(LOG_ERR, "Postingfilter \"%s\" returned error %d while processing posting " \ + "for list \"%s\".", ListConfig->postingfilter, rc, listname); + exit(1); + } + debug((DEBUG_HERMES, 6, "Filter was successful: returncode = %d.", rc)); + } + + /* Deliver the article to all recipients. */ + + rc = ListMail(envelope, listname, MailStruct); + if (rc != 0) { + syslog(LOG_ERR, "The attempt to deliver the article to the subscribers failed."); + exit(1); + } + + syslog(LOG_INFO, "Posted article from \"%s\" to list \"%s\" successfully.", + MailStruct->From, listname); + + /* Archive the article. */ + + ArchiveMail(MailStruct, listname); + + return 0; +} Index: ossp-pkg/petidomo/index.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/index.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/index.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/index.c' 2>/dev/null --- ossp-pkg/petidomo/index.c +++ - 2024-05-10 12:04:46.010761647 +0200 @@ -0,0 +1,152 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include +#include + +#include +#include + +int +GenIndex(struct Mail * MailStruct, + const char * param1, + const char * param2, + const char * defaultlist) +{ + const struct PD_Config * MasterConfig = getMasterConfig(); + const struct List_Config * ListConfig; + FILE * fh; + const char * address = NULL; + char from[4096]; + char envelope[4096]; + char * description; + char * currLine; + char * nextLine; + char * buffer; + DIR * dirp; + struct dirent * entry; + unsigned int entry_num; + + debug((DEBUG_COMMAND, 3, "GenIndex(\"%s\", \"%s\") with default list \"%s\".", + param1, param2, defaultlist)); + + address = (MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From; + + /* Initialize internal stuff. */ + + MasterConfig = getMasterConfig(); + sprintf(envelope, "petidomo-manager@%s", MasterConfig->fqdn); + if (defaultlist != NULL) + sprintf(from, "%s-request@%s", defaultlist, MasterConfig->fqdn); + else + sprintf(from, "petidomo@%s", MasterConfig->fqdn); + + /* Open the mailer. */ + + fh = vOpenMailer(envelope, address, NULL); + if (fh == NULL) { + syslog(LOG_ERR, "Failed to send mail to \"%s\": %m", address); + return -1; + } + fprintf(fh, "From: %s (Petidomo Mailing List Server)\n", from); + fprintf(fh, "To: %s\n", address); + fprintf(fh, "Subject: Your request \"index\"\n"); + if (MailStruct->Message_Id != NULL) + fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id); + fprintf(fh, "Precedence: junk\n"); + fprintf(fh, "Sender: %s\n", envelope); + fprintf(fh, "\n"); + fprintf(fh, "Index of available lists:\n"); + fprintf(fh, "=========================\n\n"); + + /* Scan the directory. */ + + entry_num = 0; + dirp = opendir("lists"); + if (dirp == NULL) { + fprintf(fh, \ +"An internal error has occured while processing your request. The\n" \ +"server administrator has been notified. You don't need to re-submit\n" \ +"your request, it will be processed as soon as the problem has been\n" \ +"remedied.\n"); + CloseMailer(fh); + syslog(LOG_ERR, "Failed to read directory \"lists\": %m"); + return -1; + } + while((entry = readdir(dirp)) != NULL) { + if (!strcasecmp(entry->d_name, ".") || !strcasecmp(entry->d_name, "..")) + continue; + if (isValidListName(entry->d_name) == FALSE) + continue; + debug((DEBUG_COMMAND, 5, "Found entry \"lists/%s\".", entry->d_name)); + + ListConfig = getListConfig(entry->d_name); + if (ListConfig->showonindex == FALSE) { + debug((DEBUG_COMMAND, 5, "List \"%s\" won't appear on the index.", + entry->d_name)); + continue; + } + entry_num++; + + /* Print stuff to the mail. */ + + fprintf(fh, "%s", entry->d_name); + { + int i; + i = 40 - strlen(entry->d_name); + if (i < 1) + i = 1; + while(i-- > 0) + fputc(' ', fh); + } + if (ListConfig->allowpubsub == TRUE) { + if (ListConfig->listtype == LIST_MODERATED) + fprintf(fh, "moderated mailing list\n"); + else + fprintf(fh, "public mailing list\n"); + } + else + fprintf(fh, "closed mailing list\n"); + + buffer = text_easy_sprintf("lists/%s/description", entry->d_name); + description = loadfile(buffer); + if (description == NULL) { + fprintf(fh, "\tno description available\n\n"); + continue; + } + + for (currLine = description; *currLine != '\0'; currLine = nextLine) { + nextLine = text_find_next_line(currLine); + if (nextLine[-1] == '\n') + nextLine[-1] = '\0'; + fprintf(fh, "\t%s\n", currLine); + } + fprintf(fh, "\n"); + free(description); + } + closedir(dirp); + + switch (entry_num) { + case 0: + fprintf(fh, "No mailing lists found.\n"); + break; + case 1: + fprintf(fh, "Found %d mailing list.\n", entry_num); + break; + default: + fprintf(fh, "Found %d mailing lists.\n", entry_num); + } + + AppendSignature(fh); + CloseMailer(fh); + + return 0; +} Index: ossp-pkg/petidomo/io.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/io.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/io.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/io.c' 2>/dev/null --- ossp-pkg/petidomo/io.c +++ - 2024-05-10 12:04:46.013389382 +0200 @@ -0,0 +1,137 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1997 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include +#include + +#include + +char * +LoadFromDescriptor(int fd) +{ + char * buffer; + unsigned int buffer_size; + unsigned int read_size; + ssize_t rc; + + buffer_size = 8 * 1024; + read_size = 0; + buffer = malloc(buffer_size); + if (buffer == NULL) { + syslog(LOG_ERR, "Failed to allocate %u byte of memory.", buffer_size); + return NULL; + } + + for (;;) { + rc = read(fd, (buffer+read_size), (buffer_size - read_size - 1)); + if (rc == -1) { + syslog(LOG_ERR, "Error occured while reading file: %m"); + free(buffer); + return NULL; + } + else if (rc == 0) { /* EOF */ + break; + } + else { /* Read succeeded normally */ + read_size += rc; + if ((buffer_size - read_size) <= 1) { /* re-allocate larger buffer */ + char * new_buffer; + buffer_size += 4 * 1024; + new_buffer = realloc(buffer, buffer_size); + if (new_buffer == NULL) { + syslog(LOG_ERR, "Failed to allocate %u byte of memory.", buffer_size); + free(buffer); + return NULL; + } + else + buffer = new_buffer; + } + } + } + buffer[read_size] = '\0'; /* terminate read data */ + errno = read_size; + return buffer; +} + + +char * +loadfile(const char * filename) +{ + struct flock lock; + char * buffer; + int fd; + int len; + int rc; + + assert(filename); + + if ((fd = open(filename, O_RDONLY, 0)) == -1) { + syslog(LOG_WARNING, "open(\"%s\", O_RDONLY): %m", filename); + return NULL; + } + lock.l_start = 0; + lock.l_len = 0; + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + fcntl(fd, F_SETLKW, &lock); + if ((len = lseek(fd, 0, SEEK_END)) == -1) { + syslog(LOG_WARNING, "lseek(\"%s\", SEEK_END): %m", filename); + return NULL; + } + if ((lseek(fd, 0, SEEK_SET) == -1)) { + syslog(LOG_WARNING, "lseek(\"%s\", SEEK_SET): %m", filename); + return NULL; + } + buffer = malloc(len+1); + if (buffer == NULL) { + syslog(LOG_WARNING, "Failed to allocate %d byte of memory.", len+1); + return NULL; + } + rc = read(fd, buffer, len); + if (rc != len) { + syslog(LOG_WARNING, "read(\"%s\", %d) read %d byte: %m", filename, len, rc); + return NULL; + } + buffer[len] = '\0'; + close(fd); + errno = len; + return buffer; +} + + +int +savefile(const char * filename, const char * buffer) +{ + struct flock lock; + int fd, len; + ssize_t rc; + + assert(filename && buffer); + + len = strlen(buffer); + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + lock.l_start = 0; + lock.l_len = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + fcntl(fd, F_SETLKW, &lock); + if (fd == -1) { + syslog(LOG_ERR, "open(\"%s\"): %m", filename); + return -1; + } + rc = write(fd, buffer, len); + if (rc == -1) { + syslog(LOG_ERR, "Error occured while writing to file \"%s\": %m", filename); + close(fd); + return -1; + } + close(fd); + return 0; +} Index: ossp-pkg/petidomo/listserv.c RCS File: /v/ossp/cvs/ossp-pkg/petidomo/listserv.c,v co -q -kk -p'1.1.1.1' '/v/ossp/cvs/ossp-pkg/petidomo/listserv.c,v' | diff -u /dev/null - -L'ossp-pkg/petidomo/listserv.c' 2>/dev/null --- ossp-pkg/petidomo/listserv.c +++ - 2024-05-10 12:04:46.016055091 +0200 @@ -0,0 +1,144 @@ +/* + * $Source$ + * $Revision$ + * $Date$ + * + * Copyright (C) 1996 by CyberSolutions GmbH. + * All rights reserved. + */ + +#include +#include + +#include +#include + +char * g_currLine; /* pointer to the line currently parsed */ + +int +listserv_main(char * incoming_mail, char * default_list) +{ + const struct List_Config * ListConfig; + struct Mail * MailStruct; + char * nextLine; + char * parameter; + char param1[512], param2[512]; + char keyword[32]; + int j, i, junklines, rc, found, operator; + + /* Initialize internals. */ + + if (default_list != NULL) + ListConfig = getListConfig(default_list); + else + ListConfig = NULL; + + /* Parse the incoming mail. */ + + rc = ParseMail(&MailStruct, incoming_mail, + (ListConfig != NULL) ? ListConfig->fqdn : NULL); + if (rc != 0) { + syslog(LOG_ERR, "Parsing the incoming mail failed."); + exit(rc); + } + debug((DEBUG_LISTSERV, 3, "Parsed incoming mail successfully.")); + + /* Do sanity checks. */ + + if (MailStruct->From == NULL) { + syslog(LOG_NOTICE, "Received mail without From: line."); + return 0; + } + + /* Do access control. */ + + if (checkACL(MailStruct, NULL, &operator, ¶meter) != 0) { + syslog(LOG_ERR, "checkACL() failed with an error."); + exit(1); + } + rc = handleACL(MailStruct, NULL, operator, parameter); + switch(rc) { + case -1: + syslog(LOG_ERR, "handleACL() failed with an error."); + exit(1); + case 0: + break; + case 1: + return 0; + } + + /* Parse the body and call the apropriate routines for each + command. */ + + g_currLine = MailStruct->Body; + if (*g_currLine == '\0') { + syslog(LOG_NOTICE, "Received mail with empty body."); + SendHelp(MailStruct, NULL, NULL, default_list); + return 0; + } + for (nextLine = text_find_next_line(g_currLine), junklines = 0, found = 0; + *g_currLine != '\0' && junklines <= 7; + g_currLine = nextLine, nextLine = text_find_next_line(g_currLine)) { + + /* remove trailing \n */ + + if (nextLine[-1] == '\n') + nextLine[-1] = '\0'; + + /* Skip comments, signature and empty lines. */ + + if (*g_currLine == '\0' || *g_currLine == '#') + continue; + if (!strcmp(g_currLine, "-- ")) { + debug((DEBUG_LISTSERV, 6, "Ignoring trailing signature.")); + break; + } + + /* Log contents of current line. */ + + syslog(LOG_INFO, "%s: %s", + ((MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From), g_currLine); + + /* Check whether we have a routine for that command. */ + + for (j = 0; !isspace((int)g_currLine[j]) && j < (sizeof(keyword)-1); j++) + keyword[j] = g_currLine[j]; + keyword[j] = '\0'; + debug((DEBUG_LISTSERV, 5, "command is \"%s\".", keyword)); + for (i = 0; (&(ParseArray[i]))->keyword != NULL; i++) { + if (strcasecmp(keyword, (&(ParseArray[i]))->keyword) == 0) { /* hit */ + debug((DEBUG_LISTSERV, 4, "Recognized command \"%s\".", keyword)); + rc = sscanf(g_currLine, "%*s%511s%511s", param1, param2); + rc = ((&(ParseArray[i]))->handleCommand)(MailStruct, + ((rc >= 1) ? param1 : NULL), + ((rc == 2) ? param2 : NULL), + default_list); + if (rc != 0) { + syslog(LOG_ERR, "Error occured while handling command."); + exit(1); + } + found++; + break; + } + } + + if ((&(ParseArray[i]))->keyword == NULL) { + + /* No valid command. */ + + debug((DEBUG_LISTSERV, 4, "Unrecognized command \"%s\".", keyword)); + junklines++; + } + } + + if (junklines > 7) + syslog(LOG_INFO, "Too many junk lines, ignoring rest of the mail."); + + if (found == 0) { + syslog(LOG_INFO, "No valid command found, sending help file back to \"%s\".", + ((MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From)); + Indecipherable(MailStruct, default_list); + } + + return 0; +}