bug-anubis
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug-anubis] openssl and s/mime emails


From: Sergey Poznyakoff
Subject: Re: [bug-anubis] openssl and s/mime emails
Date: Thu, 09 Oct 2003 23:15:11 +0300

Hello Robert,

> Has anyone figured out how to use Anubis to do S/MIME emails using Gnu
> Anubis?

The support for S/MIME is planned for the next version. In the meantime
it is possible to use S/MIME via an external program.
 
> Unfortunately, AFAICT, anubis supports only external BODY processors,
> but for S/MIME I need to process the whole dang message.

It is possible to feed the entire message to an external program with the
alpha version of Anubis 3.9.93. Here is a short instruction:

1) Download the alpha version from anonymous

   ftp://mirddin.farlep.net/pub/alpha/anubis-3.9.93.tar.gz

MD5sum of the file is ec725d82be4b1958fd2294550728bd1e

2) You will need Guile version 1.6 or later. Make sure it is
installed on your system. Guile is available from ftp.gnu.org
(directory /gnu/guile) or its mirrors worldwide.

3) Compile and install anubis 3.9.93. Please, notice that the
configuration file syntax has changed in this version. Take a look into
file NEWS for a short summary. The detailed description of the syntax is
available in the accompanying documentation.

4) Attached is a Guile module that you can use to pass the entire
message to the program. Copy this file where it is convenient to you
(/usr/local/share/anubis will be a good place for it). To your
anubisrc add the following section:

SECTION GUILE
guile-load-path-append (directory where you put filter.scm)
guile-load-program filter.scm
END

Now, to invoke the external filter, add the following line to your
RULE section:

guile-process full-external-filter PROGNAME [ARGS...]

where PROGNAME is the name of the program to execute (preferably the
full path specification) ARGS are any arguments it may need. For
example:

trigger "smime:(.*)"
 guile-process /usr/local/bin/openssl smime -sender \1 ....
done

Feel free to write as if you have any problems or questions.

Regards,
Sergey

;;;; GNU Anubis -- an outgoing mail processor and the SMTP tunnel.
;;;; Copyright (C) 2003 The Anubis Team.
;;;;
;;;; GNU Anubis 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.
;;;;
;;;; GNU Anubis 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 GNU Anubis; if not, write to the Free Software
;;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
;;;;
;;;; GNU Anubis is released under the GPL with the additional exemption that
;;;; compiling, linking, and/or using OpenSSL is allowed.

(use-modules (ice-9 popen))

;; Starts program PROG with arguments ARGS
;; Returns a list:
;;   (PID OUTPUT-PORT INPUT-PORT)
;; Where
;;  PID          -- pid of the program
;;  OUTPUT-PORT  -- output port connected to the stdin of the program
;;  INPUT-PORT   -- input port connected to the stdout of the program
;; Note:
;;  When no longer needed, the returned list must be fed to
;;  (close-subprocess). See below.
(define (create-subprocess prog args)
  (let ((inp (pipe))
        (outp (pipe))
        (pid (primitive-fork)))
    (setvbuf (cdr inp) _IONBF)
    (setvbuf (cdr outp) _IONBF)
    ;; (car inp)  -> child current-input-port
    ;; (cdr inp)  -> parent write port
    ;; (car outp) -> parent read port
    ;; (cdr outp) -> child current-output-port
    (cond
     ((= pid 0)
      ;; Child
      (let ((in-fd (fileno (car inp)))
            (out-fd (fileno (cdr outp)))
            (err-fd (fileno (current-error-port))))
        (port-for-each (lambda (pt-entry)
                         (false-if-exception
                          (let ((pt-fileno (fileno pt-entry)))
                            (if (not (or (= pt-fileno in-fd)
                                         (= pt-fileno out-fd)
                                         (= pt-fileno err-fd)))
                                (close-fdes pt-fileno))))))
        ;; copy the three selected descriptors to the standard
        ;; descriptors 0, 1, 2.  

        (cond ((not (= in-fd 0))
               (if (= out-fd 0)
                   (set! out-fd (dup->fdes 0)))
               (if (= err-fd 0)
                   (set! err-fd (dup->fdes 0)))
               (dup2 in-fd 0)))

        (cond ((not (= out-fd 1))
               (if (= err-fd 1)
                   (set! err-fd (dup->fdes 1)))
               (dup2 out-fd 1)))
        
        (dup2 err-fd 2)
        
        (apply execlp prog prog args)))
     (else
      ;; Parent
      (close-port (car inp))
      (close-port (cdr outp))
      (list pid (cdr inp) (car outp))))))

;; Closes the communication channels and destroys the subprocess created
;; by (create-subprocess)
(define (close-subprocess p)
  (close-port (list-ref p 1))
  (close-port (list-ref p 2))
  (cdr (waitpid (car p))))

;; Auxiliary function. Asynchronously feeds data to external program.
;; Returns pid of the feeder process.
(define (writer outport hdr body)
  (let ((pid (primitive-fork)))
    (cond
     ((= pid 0)
      (with-output-to-port
          outport
        (lambda ()
          (for-each
           (lambda (x)
             (display (car x))
             (display ": ")
             (display (cdr x))
             (newline))
           hdr)
          (newline)
          (display body)))
      (port-for-each close-port)
      (primitive-exit 0))
     (else
      ;; Parent
      (close-port outport)
      pid))))

;; Auxiliary function. Returns #t if LINE is an empty line.
(define (empty-line? line)
  (or (eof-object? line)
      (string-null? line)))

;; Read RFC822 headers from current input port and convert them
;; to the form understandable by Anubis
(define (read-headers)
  (let ((hdr-list '())
        (header-name #f)
        (header-value ""))
    (do ((line (read-line) (read-line)))
        ((empty-line? line) #t)
      (cond
       ((char-whitespace? (string-ref line 0))
        (set! header-value (string-append header-value line)))
       (else
        (if header-name
            (set! hdr-list (append hdr-list
                                   (list (cons header-name header-value)))))
        (let ((off (string-index line #\:)))
          (set! header-name (substring line 0 off))
          (set! header-value (substring
                              line
                              (do ((i (1+ off) (1+ i)))
                                  ((not (char-whitespace?
                                         (string-ref line i))) i))))))))
    (if header-name
        (set! hdr-list (append hdr-list
                               (list (cons header-name header-value)))))
    hdr-list))

;; Read message body from the current input port
(define (read-body)
  (let ((text-list '()))
    (do ((line (read-line) (read-line)))
        ((eof-object? line) #t)
      (set! text-list (append text-list (list line "\n"))))
    (apply string-append text-list)))

;; Auxiliary function. Reads output from the external program and
;; converts it to the internal Anubis representation.
(define (reader inport)
    (with-input-from-port
        inport
      (lambda ()
        (cons (read-headers) (read-body))))) 

(define (optarg-value opt-args tag)
  (cond
   ((member tag opt-args) =>
    (lambda (x)
      (car (cdr x))))
   (else
    #f)))

;; A Guile interface for feeding the entire message (including headers)
;; to an external program.
;;
;; Usage:
;;   SECTION GUILE
;;   guile-load-program filter.scm
;;   END
;;
;;   guile-process full-external-filter PROGNAME [ARGS...]

(define (full-external-filter hdr body . rest)
  (let ((progname (car rest))
        (args (cdr rest)))
    (let* ((p (create-subprocess progname args))
           (wrpid (writer (list-ref p 1) hdr body)))
      (let ((ret (reader (list-ref p 2))))
        (waitpid wrpid)
        (close-subprocess p)
        ret))))

;; End of filter.scm

reply via email to

[Prev in Thread] Current Thread [Next in Thread]