Back to index

courier  0.68.2
Classes | Defines | Functions
gpg.c File Reference
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include "mimegpgheader.h"
#include "mimegpgstack.h"
#include "mimegpgfork.h"
#include "tempname.h"
#include "gpglib.h"
#include "rfc822/encode.h"
#include "rfc2045/rfc2045.h"

Go to the source code of this file.

Classes

struct  gpg_fork_output_info
struct  libmail_gpg_errhandler

Defines

#define WEXITSTATUS(stat_val)   ((unsigned)(stat_val) >> 8)
#define WIFEXITED(stat_val)   (((stat_val) & 255) == 0)
#define C(s)   (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S(s)   (*output_func)( s, strlen(s), output_func_arg)
#define C(s)   (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S(s)   (*output_func)( s, strlen(s), output_func_arg)
#define C(s)   (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S(s)   (*output_func)( s, strlen(s), output_func_arg)

Functions

static int my_rewind (FILE *fp)
int libmail_gpg_inputfunc_readfp (char *buf, size_t cnt, void *vp)
void libmail_gpg_noexec (int fd)
static struct mimestackis_boundary (struct mimestack *s, const char *line, int *isclosing)
static const char * get_boundary (struct mimestack *, const char *, FILE *)
static void find_boundary (struct mimestack **stack, int *iseof, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg, int doappend)
static struct headerread_headers (struct mimestack **stack, int *iseof, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg, int doappend, int *errflag)
static int encode_header (const char *h)
static int gpg_fork_output (const char *p, size_t n, void *dummy)
static int dogpgencrypt (const char *gpghome, const char *passphrase_fd, struct mimestack **stack, struct header *h, int *iseof, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg, int argc, char **argv, int dosign, void(*errhandler)(const char *, void *), void *errhandler_arg)
static int dogpgsign (const char *gpghome, const char *passphrase_fd, struct mimestack **stack, struct header *h, int *iseof, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg, int argc, char **argv, void(*errhandler)(const char *, void *), void *errhandler_arg)
static int isgpg (struct mime_header *)
static int checksign (const char *gpghome, const char *passphrase_fd, struct mimestack **, int *, struct header *, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*)(const char *, size_t, void *), void *, int, char **, int *)
static int decrypt (const char *gpghome, const char *passphrase_fd, struct mimestack **, int *, struct header *, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*)(const char *, size_t, void *), void *, int, char **, int *)
static void print_noncontent_headers (struct header *h, void(*output_func)(const char *, size_t, void *), void *output_func_arg)
static int dosignencode2 (int dosign, int doencode, int dodecode, const char *gpghome, const char *passphrase_fd, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg, void(*errhandler_func)(const char *, void *), void *errhandler_arg, int argc, char **argv, int *status)
static int nybble (char c)
static int dochecksign (const char *, const char *, struct mimestack *, FILE *, void(*output_func)(const char *, size_t, void *), void *output_func_arg, const char *, const char *, int, char **, int *)
static const char * newboundary ()
static int good_boundary (const char *boundary, struct mimestack *m, const char *errmsg, FILE *fp)
static const char * encoding_str (const char *p)
static int copyfp (FILE *t, void(*output_func)(const char *, size_t, void *), void *output_func_arg, int stripcr)
static void open_result_multipart (void(*)(const char *, size_t, void *), void *, int, const char *, const char *, const char *)
static void close_mime (struct mimestack **stack, int *iseof, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg)
static int dodecrypt (const char *, const char *, struct mimestack **, int *, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, FILE *, int, char **, const char *, void(*)(const char *, size_t, void *), void *, int *)
static void write_temp_fp (const char *p, size_t n, void *vp)
static int dumpdecrypt (const char *c, size_t n, void *vp)
static void libmail_gpg_errfunc (const char *errmsg, void *vp)
static int input_func_from_fp (char *buf, size_t cnt, void *vp)
static int dosignencode (int dosign, int doencode, int dodecode, const char *gpghome, const char *passphrase_fd, int(*input_func)(char *, size_t, void *vp), void *input_func_arg, void(*output_func)(const char *, size_t, void *), void *output_func_arg, void(*errhandler_func)(const char *, void *), void *errhandler_arg, int argc, char **argv, int *status)
int libmail_gpg_signencode (int dosign, int doencode, struct libmail_gpg_info *options)
int libmail_gpg_decode (int mode, struct libmail_gpg_info *options)

Class Documentation

struct libmail_gpg_errhandler

Definition at line 1966 of file gpg.c.

Collaboration diagram for libmail_gpg_errhandler:
Class Members
int err_flag
struct libmail_gpg_info * options

Define Documentation

#define C (   s)    (*output_func)( s, sizeof(s)-1, output_func_arg)
#define C (   s)    (*output_func)( s, sizeof(s)-1, output_func_arg)
#define C (   s)    (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S (   s)    (*output_func)( s, strlen(s), output_func_arg)
#define S (   s)    (*output_func)( s, strlen(s), output_func_arg)
#define S (   s)    (*output_func)( s, strlen(s), output_func_arg)
#define WEXITSTATUS (   stat_val)    ((unsigned)(stat_val) >> 8)

Definition at line 26 of file gpg.c.

#define WIFEXITED (   stat_val)    (((stat_val) & 255) == 0)

Definition at line 29 of file gpg.c.


Function Documentation

static int checksign ( const char *  gpghome,
const char *  passphrase_fd,
struct mimestack **  stack,
int *  iseof,
struct header h,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  argc,
char **  argv,
int *  errptr 
) [static]

Definition at line 1108 of file gpg.c.

{
       char buf[BUFSIZ];
       struct header *h2;

       char signed_content[TEMPNAMEBUFSIZE];
       char signature[TEMPNAMEBUFSIZE];
       int signed_file, signature_file;
       FILE *signed_file_fp, *signature_file_fp;
       int clos_flag;
       int need_nl, check_boundary;
       struct mimestack *b=0;
       struct mime_header *mh;
       int qpdecode=0;
       int errflag;

       *errptr=0;

       signed_file=libmail_tempfile(signed_content);

       if (signed_file < 0 || (signed_file_fp=fdopen(signed_file, "w+")) == 0)
       {
              if (signed_file > 0)
              {
                     close(signed_file);
                     unlink(signed_content);
              }
              return -1;
       }
       libmail_gpg_noexec(fileno(signed_file_fp));

       find_boundary(stack, iseof, input_func,
                    input_func_arg, NULL, NULL, 0);
       if (*iseof)
              return 0;

       need_nl=0;
       check_boundary=1;

       while (!*iseof)
       {
              const char *p;

              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     continue;
              }

              if (check_boundary
                  && (b=is_boundary(*stack, buf, &clos_flag)) != 0)
                     break;
              if (need_nl)
                     fprintf(signed_file_fp, "\r\n");

              for (p=buf; *p && *p != '\n'; p++)
                     putc(*p, signed_file_fp);
              need_nl=check_boundary= *p != 0;
       }

       if (my_rewind(signed_file_fp) < 0)
       {
              fclose(signed_file_fp);
              unlink(signed_content);
              return -1;
       }

       if (clos_flag)
       {
              fclose(signed_file_fp);
              unlink(signed_content);
              if (b)
                     libmail_mimestack_pop_to(stack, b);
              find_boundary(stack, iseof, input_func, input_func_arg,
                           output_func, output_func_arg, 1);
              return 0;
       }

       h=read_headers(stack, iseof, input_func, input_func_arg,
                     output_func, output_func_arg, 0, &errflag);

       if (errflag)
       {
              fclose(signed_file_fp);
              unlink(signed_content);

              return (-1);
       }

       if (!h || !(h2=libmail_header_find(h, "content-type:")))
       {
              if (h)
                     libmail_header_free(h);
              fclose(signed_file_fp);
              unlink(signed_content);
              if (!*iseof)
                     find_boundary(stack, iseof, input_func, input_func_arg,
                                  output_func, output_func_arg, 1);
              return 0;
       }

       mh=libmail_mimeheader_parse(h2->header+sizeof("content-type:")-1);

       if (!mh)
       {
              libmail_header_free(h);
              fclose(signed_file_fp);
              unlink(signed_content);
              return (-1);
       }

       if (strcasecmp(mh->header_name, "application/pgp-signature"))
       {
              libmail_mimeheader_free(mh);
              libmail_header_free(h);
              fclose(signed_file_fp);
              unlink(signed_content);
              if (!*iseof)
                     find_boundary(stack, iseof, input_func, input_func_arg,
                                  output_func, output_func_arg, 1);
              return (0);
       }
       libmail_mimeheader_free(mh);

       /*
       ** In rare instances, the signature is qp-encoded.
       */

       if ((h2=libmail_header_find(h, "content-transfer-encoding:")) != NULL)
       {
              mh=libmail_mimeheader_parse
                     (h2->header+sizeof("content-transfer-encoding:")-1);

              if (!mh)
              {
                     libmail_header_free(h);
                     fclose(signed_file_fp);
                     unlink(signed_content);
                     return -1;
              }

              if (strcasecmp(mh->header_name,
                            "quoted-printable") == 0)
                     qpdecode=1;
              libmail_mimeheader_free(mh);
       }
       libmail_header_free(h);

       signature_file=libmail_tempfile(signature);

       if (signature_file < 0
           || (signature_file_fp=fdopen(signature_file, "w+")) == 0)
       {
              if (signature_file > 0)
              {
                     close(signature_file);
                     unlink(signature);
              }
              unlink(signed_content);
              return (-1);
       }

       while (!*iseof)
       {
              const char *p;

              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     continue;
              }

              if ((b=is_boundary(*stack, buf, &clos_flag)) != 0)
                     break;

              for (p=buf; *p; p++)
              {
                     int n;

                     if (!qpdecode)
                     {
                            putc(*p, signature_file_fp);
                            continue;
                     }

                     if (*p == '=' && p[1] == '\n')
                            break;

                     if (*p == '=' && p[1] && p[2])
                     {
                            n=nybble(p[1]) * 16 + nybble(p[2]);
                            if ( (char)n )
                            {
                                   putc((char)n, signature_file_fp);
                                   p += 2;
                            }
                            p += 2;
                            continue;
                     }
                     putc(*p, signature_file_fp);

                     /* If some spits out qp-lines > BUFSIZ, they deserve
                     ** this crap.
                     */
              }
       }

       fflush(signature_file_fp);
       if (ferror(signature_file_fp))
       {
              unlink(signature);
              fclose(signed_file_fp);
              unlink(signed_content);
              return -1;
       }
       if (fclose(signature_file_fp))
       {
              unlink(signature);
              unlink(signed_content);
              return -1;
       }

       errflag=dochecksign(gpghome,
                         passphrase_fd,
                         *stack, signed_file_fp,
                         output_func, output_func_arg, signed_content,
                         signature,
                         argc, argv, errptr);

       fclose(signed_file_fp);
       unlink(signature);
       unlink(signed_content);

       if (errflag)
              return -1;

       while (!clos_flag)
       {
              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     break;
              }
              if (!(b=is_boundary(*stack, buf, &clos_flag)))
                     clos_flag=0;
       }
       if (b)
              libmail_mimestack_pop_to(stack, b);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void close_mime ( struct mimestack **  stack,
int *  iseof,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg 
) [static]

Definition at line 1582 of file gpg.c.

{
       char buf[BUFSIZ];
       int is_closing;
       struct mimestack *b;

       for (;;)
       {
              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     break;
              }

              (*output_func)(buf, strlen(buf), output_func_arg);
              if (!(b=is_boundary(*stack, buf, &is_closing)))
                     continue;
              if (!is_closing)
                     continue;

              libmail_mimestack_pop_to(stack, b);
              break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int copyfp ( FILE *  t,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  stripcr 
) [static]

Definition at line 1450 of file gpg.c.

{
       char buf[BUFSIZ];
       int rc=0;

       while ((rc=fread(buf, 1, sizeof(buf), t)) > 0)
       {
              if (stripcr)
              {
                     int i, j;

                     for (i=j=0; i<rc; ++i)
                     {
                            if (buf[i] != '\r')
                                   buf[j++]=buf[i];
                     }
                     rc=j;
              }
              (*output_func)(buf, rc, output_func_arg);
       }

       return rc;
}

Here is the caller graph for this function:

static int decrypt ( const char *  gpghome,
const char *  passphrase_fd,
struct mimestack **  stack,
int *  iseof,
struct header h,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  argc,
char **  argv,
int *  errptr 
) [static]

Definition at line 1630 of file gpg.c.

{
       struct header *p, *q;
       char temp_file[TEMPNAMEBUFSIZE];
       int temp_fd;
       FILE *temp_fp;
       struct mime_header *mh;
       int flag;
       int errflag;

       *errptr=0;
       temp_fd=libmail_tempfile(temp_file);
       if (temp_fd < 0 || (temp_fp=fdopen(temp_fd, "w+")) == 0)
       {
              if (temp_fd >= 0)
                     close(temp_fd);
              return -1;
       }

       for (p=h; p; p=p->next)
       {
              fprintf(temp_fp, "%s", p->header);
       }
       putc('\n', temp_fp);

       find_boundary(stack, iseof, input_func, input_func_arg,
                    write_temp_fp, temp_fp, 0);
       if (*iseof)
       {
              fclose(temp_fp);
              unlink(temp_file);
              return (0);
       }

       p=read_headers(stack, iseof, input_func, input_func_arg, write_temp_fp,
                     temp_fp, 0, &errflag);

       if (*iseof || errflag)
       {
              libmail_header_free(p);
              fclose(temp_fp);
              unlink(temp_file);

              if (errflag)
                     return -1;
              return 0;
       }

       q=libmail_header_find(p, "content-type:");

       flag=0;

       if (q)
       {
              mh=libmail_mimeheader_parse(q->header+13);
              if (!mh)
              {
                     libmail_header_free(p);
                     fclose(temp_fp);
                     unlink(temp_file);
                     return -1;
              }

              if (strcasecmp(mh->header_name, "application/pgp-encrypted")
                  == 0)
                     flag=1;
              libmail_mimeheader_free(mh);
       }

       for (q=p; q; q=q->next)
       {
              fprintf(temp_fp, "%s", q->header);
       }
       libmail_header_free(p);
       putc('\n', temp_fp);

       p=read_headers(stack, iseof, input_func, input_func_arg,
                     write_temp_fp, temp_fp, 0,
                     &errflag);

       if (*iseof || errflag)
       {
              libmail_header_free(p);
              fclose(temp_fp);
              unlink(temp_file);

              if (errflag)
                     return -1;

              return 0;
       }

       q=libmail_header_find(p, "version:");

       if (flag)
       {
              if (!q || atoi(p->header + 8) != 1)
                     flag=0;
       }
       for (q=p; q; q=q->next)
       {
              fprintf(temp_fp, "%s", q->header);
       }
       libmail_header_free(p);
       putc('\n', temp_fp);

       find_boundary(stack, iseof, input_func, input_func_arg,
                    write_temp_fp, temp_fp, 0);

       if (*iseof)
       {
              fclose(temp_fp);
              unlink(temp_file);
              return 0;
       }

       p=read_headers(stack, iseof, input_func, input_func_arg, write_temp_fp,
                     temp_fp, 0, &errflag);

       if (*iseof || errflag)
       {
              libmail_header_free(p);
              fclose(temp_fp);
              unlink(temp_file);

              if (errflag)
                     return -1;

              return 0;
       }

       q=libmail_header_find(p, "content-type:");

       if (q && flag)
       {
              flag=0;
              mh=libmail_mimeheader_parse(q->header+13);
              if (!mh)
              {
                     libmail_header_free(p);
                     fclose(temp_fp);
                     unlink(temp_file);
                     return -1;
              }

              if (strcasecmp(mh->header_name, "application/octet-stream")
                  == 0)
                     flag=1;
              libmail_mimeheader_free(mh);

              q=libmail_header_find(p, "content-transfer-encoding:");
              if (q && flag)
              {
                     flag=0;
                     mh=libmail_mimeheader_parse(strchr(q->header, ':')+1);
                     if (!mh)
                     {
                            libmail_header_free(p);
                            fclose(temp_fp);
                            unlink(temp_file);
                            return -1;
                     }

                     if (strcasecmp(mh->header_name, "7bit") == 0 ||
                         strcasecmp(mh->header_name, "8bit") == 0)
                            flag=1;
                     libmail_mimeheader_free(mh);
              }
       }

       for (q=p; q; q=q->next)
       {
              fprintf(temp_fp, "%s", q->header);
       }
       libmail_header_free(p);
       putc('\n', temp_fp);

       if (fflush(temp_fp) || ferror(temp_fp) || my_rewind(temp_fp) < 0)
       {
              fclose(temp_fp);
              unlink(temp_file);
              return -1;
       }

       if (!flag)
       {
              int c=copyfp(temp_fp, output_func, output_func_arg, 0);

              fclose(temp_fp);
              unlink(temp_file);
              close_mime(stack, iseof, input_func, input_func_arg,
                        output_func, output_func_arg);
              return (c);
       }

       fclose(temp_fp);
       if ((temp_fp=fopen(temp_file, "w+")) == NULL)
       {
              unlink(temp_file);
              return (-1);
       }
       libmail_gpg_noexec(fileno(temp_fp));
       errflag=dodecrypt(gpghome, passphrase_fd,
                       stack, iseof, input_func, input_func_arg,
                       temp_fp, argc, argv, temp_file,
                       output_func, output_func_arg, errptr);
       fclose(temp_fp);
       unlink(temp_file);
       return errflag;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dochecksign ( const char *  gpghome,
const char *  passphrase_fd,
struct mimestack stack,
FILE *  content_fp,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
const char *  content_filename,
const char *  signature_filename,
int  argc,
char **  argv,
int *  errptr 
) [static]

Definition at line 1484 of file gpg.c.

{
       struct gpgmime_forkinfo gpg;
       int i;
       const char *new_boundary;
       const char *output;

       if (libmail_gpgmime_forkchecksign(gpghome, passphrase_fd,
                              content_filename,
                              signature_filename,
                              argc, argv,
                              &gpg))
       {
              return -1;
       }

       *errptr=i=libmail_gpgmime_finish(&gpg);

       output=libmail_gpgmime_getoutput(&gpg);

       new_boundary=get_boundary(stack, output, content_fp);

       open_result_multipart(output_func, output_func_arg,
                           i, new_boundary, output,
                           libmail_gpgmime_getcharset(&gpg));

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(new_boundary, strlen(new_boundary), output_func_arg);
       (*output_func)("\n", 1, output_func_arg);

       if (my_rewind(content_fp) < 0)
       {
              return -1;
       }

       if (copyfp(content_fp, output_func, output_func_arg, 1))
              return -1;

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(new_boundary, strlen(new_boundary), output_func_arg);
       (*output_func)("--\n", 3, output_func_arg);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dodecrypt ( const char *  gpghome,
const char *  passphrase_fd,
struct mimestack **  stack,
int *  iseof,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
FILE *  fpout,
int  argc,
char **  argv,
const char *  temp_file,
void(*)(const char *,size_t,void *)  output_func,
void *  output_func_arg,
int *  errptr 
) [static]

Definition at line 1864 of file gpg.c.

{
       struct gpgmime_forkinfo gpg;
       char buf[BUFSIZ];
       int is_closing;
       struct mimestack *b=NULL;
       int dowrite=1;
       int rc;
       const char *new_boundary;
       const char *output;

       if (libmail_gpgmime_forkdecrypt(gpghome,
                            passphrase_fd,
                            argc, argv, &dumpdecrypt, fpout, &gpg))
              return -1;

       for (;;)
       {
              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     break;
              }

              if (dowrite)
                     libmail_gpgmime_write(&gpg, buf, strlen(buf));

              if (!(b=is_boundary(*stack, buf, &is_closing)))
                     continue;
              dowrite=0;
              if (!is_closing)
                     continue;
              break;
       }

       rc=libmail_gpgmime_finish(&gpg);
       if (fflush(fpout) || ferror(fpout) || my_rewind(fpout) < 0)
       {
              fclose(fpout);
              unlink(temp_file);
              return -1;
       }

       if (*iseof)
              return 0;

       output=libmail_gpgmime_getoutput(&gpg),

       new_boundary=get_boundary(*stack, output, rc ? NULL:fpout);

       open_result_multipart(output_func,
                           output_func_arg, rc, new_boundary,
                           output,
                           libmail_gpgmime_getcharset(&gpg));

       *errptr=rc;

#if 0

       /*
       ** gnupg returns non-zero exit even if succesfully unencrypted, when
       ** just the signature is bad.
       */
       if (rc == 0)
#endif
       {
              if (fseek(fpout, 0L, SEEK_SET) < 0)
              {
                     fclose(fpout);
                     unlink(temp_file);
                     return -1;
              }

              (*output_func)("\n--", 3, output_func_arg);
              (*output_func)(new_boundary, strlen(new_boundary),
                            output_func_arg);
              (*output_func)("\n", 1, output_func_arg);

              if (copyfp(fpout, output_func, output_func_arg, 1))
                  return -1;
       }

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(new_boundary, strlen(new_boundary),
                     output_func_arg);
       (*output_func)("--\n", 3, output_func_arg);

       libmail_mimestack_pop_to(stack, b);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dogpgencrypt ( const char *  gpghome,
const char *  passphrase_fd,
struct mimestack **  stack,
struct header h,
int *  iseof,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  argc,
char **  argv,
int  dosign,
void(*)(const char *, void *)  errhandler,
void *  errhandler_arg 
) [static]

Definition at line 303 of file gpg.c.

{
       struct header *hp;
       char buf[BUFSIZ];
       struct gpgmime_forkinfo gpg;
       int clos_flag=0;
       struct mimestack *b=0;
       int rc;
       const char *boundary;
       int need_crlf;
       struct gpg_fork_output_info gfoi;

       boundary=get_boundary(*stack, "", NULL);

       gfoi.output_func=output_func;
       gfoi.output_func_arg=output_func_arg;

       if (libmail_gpgmime_forksignencrypt(gpghome, passphrase_fd,
                                       (dosign ? GPG_SE_SIGN:0)
                                       | GPG_SE_ENCRYPT,
                                       argc, argv,
                                       &gpg_fork_output, &gfoi,
                                       &gpg))
       {
              return -1;
       }

       for (hp=h; hp; hp=hp->next)
       {
              if (encode_header(hp->header))
                     continue;

              (*output_func)(hp->header, strlen(hp->header),
                            output_func_arg);
       }

#define C(s) (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S(s) (*output_func)( s, strlen(s), output_func_arg)


       C("Content-Type: multipart/encrypted;\n"
         "    boundary=\"");

       S(boundary);

       C("\";\n"
         "    protocol=\"application/pgp-encrypted\"\n"
         "\n"
         "This is a MIME GnuPG-encrypted message.  If you see this text, it means\n"
         "that your E-mail or Usenet software does not support MIME encrypted messages.\n"
         "The Internet standard for MIME PGP messages, RFC 2015, was published in 1996.\n"
         "To open this message correctly you will need to install E-mail or Usenet\n"
         "software that supports modern Internet standards.\n"
         "\n--");

       S(boundary);

       C("\n"
         "Content-Type: application/pgp-encrypted\n"
         "Content-Transfer-Encoding: 7bit\n"
         "\n"
         "Version: 1\n"
         "\n--");

       S(boundary);

       C("\n"
         "Content-Type: application/octet-stream\n"
         "Content-Transfer-Encoding: 7bit\n\n");

#undef C
#undef S

       /* For Eudora compatiblity */
        libmail_gpgmime_write(&gpg, "Mime-Version: 1.0\r\n", 19);

       for (hp=h; hp; hp=hp->next)
       {
              const char *p;

              if (!encode_header(hp->header))
                     continue;

              for (p=hp->header; *p; p++)
              {
                     if (*p == '\r')
                            continue;

                     if (*p == '\n')
                            libmail_gpgmime_write(&gpg, "\r\n", 2);
                     else
                            libmail_gpgmime_write(&gpg, p, 1);
              }
       }

       /*
       ** Chew the content until the next MIME boundary.
       */
       need_crlf=1;

       while (!*iseof)
       {
              const char *p;

              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     break;
              }

              if (need_crlf)
              {
                     if ((b=is_boundary(*stack, buf, &clos_flag)) != NULL)
                            break;

                     libmail_gpgmime_write(&gpg, "\r\n", 2);
              }

              need_crlf=0;
              for (;;)
              {
                     for (p=buf; *p; p++)
                     {
                            if (*p == '\r')
                                   continue;
                            if (*p == '\n')
                            {
                                   need_crlf=1;
                                   break;
                            }

                            libmail_gpgmime_write(&gpg, p, 1);
                     }
                     if (*p == '\n')
                            break;

                     if ( (*input_func)(buf, sizeof(buf), input_func_arg))
                     {
                            *iseof=1;
                            break;
                     }
              }
       }

       /*
       ** This needs some 'splainin.  Note that we spit out a newline at
       ** the BEGINNING of each line, above.  This generates the blank
       ** header->body separator line.  Now, if we're NOT doing multiline
       ** content, we need to follow the last line of the content with a
       ** newline.  If we're already doing multiline content, that extra
       ** newline (if it exists) is already there.
       */

       if (!*stack)
       {
              libmail_gpgmime_write(&gpg, "\r\n", 2);
       }

       rc=libmail_gpgmime_finish(&gpg);

       if (rc)
       {
              (*errhandler)(libmail_gpgmime_getoutput(&gpg), errhandler_arg);
              return (-1);
       }

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(boundary, strlen(boundary), output_func_arg);
       (*output_func)("--\n", 3, output_func_arg);

       if (*iseof)
              return 0;

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(b->boundary, strlen(b->boundary), output_func_arg);
       if (clos_flag)
              (*output_func)("--", 2, output_func_arg);
       (*output_func)("\n", 1, output_func_arg);

       if (clos_flag)
       {
              libmail_mimestack_pop_to(stack, b);
              find_boundary(stack, iseof, input_func,
                           input_func_arg, output_func,
                           output_func_arg, 1);
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dogpgsign ( const char *  gpghome,
const char *  passphrase_fd,
struct mimestack **  stack,
struct header h,
int *  iseof,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  argc,
char **  argv,
void(*)(const char *, void *)  errhandler,
void *  errhandler_arg 
) [static]

Definition at line 507 of file gpg.c.

{
       struct header *hp;
       char buf[8192];
       struct gpgmime_forkinfo gpg;
       int clos_flag=0;
       struct mimestack *b=0;
       int rc=0;
       char signed_content_name[TEMPNAMEBUFSIZE];
       int signed_content;
       FILE *signed_content_fp;
       const char *boundary;
       int need_crlf;
       struct gpg_fork_output_info gfoi;

       for (hp=h; hp; hp=hp->next)
       {
              if (encode_header(hp->header))
                     continue;
              (*output_func)(hp->header, strlen(hp->header),
                            output_func_arg);
       }

       signed_content=libmail_tempfile(signed_content_name);
       if (signed_content < 0 ||
           (signed_content_fp=fdopen(signed_content, "w+")) == NULL)
       {
              if (signed_content >= 0)
              {
                     close(signed_content);
                     unlink(signed_content_name);
              }
              return -1;

       }
       libmail_gpg_noexec(fileno(signed_content_fp));
       unlink(signed_content_name);       /* UNIX semantics */

       for (hp=h; hp; hp=hp->next)
       {
              const char *p;

              if (!encode_header(hp->header))
                     continue;

              for (p=hp->header; *p; p++)
              {
                     if (*p == '\r')
                            continue;

                     if (*p == '\n')
                            putc('\r', signed_content_fp);
                     putc(*p, signed_content_fp);
              }
       }

       /*
       ** Chew the content until the next MIME boundary.
       */
       need_crlf=1;
       while (!*iseof)
       {
              const char *p;

              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     break;
              }

              if (need_crlf)
              {
                     if ((b=is_boundary(*stack, buf, &clos_flag)) != NULL)
                            break;

                     fprintf(signed_content_fp, "\r\n");
              }

              need_crlf=0;
              for (;;)
              {
                     for (p=buf; *p; p++)
                     {
                            if (*p == '\r')
                                   continue;
                            if (*p == '\n')
                            {
                                   need_crlf=1;
                                   break;
                            }

                            putc(*p, signed_content_fp);
                     }
                     if (*p == '\n')
                            break;

                     if ( (*input_func)(buf, sizeof(buf), input_func_arg))
                     {
                            *iseof=1;
                            break;
                     }
              }
       }

       /*
       ** This needs some 'splainin.  Note that we spit out a newline at
       ** the BEGINNING of each line, above.  This generates the blank
       ** header->body separator line.  Now, if we're NOT doing multiline
       ** content, we need to follow the last line of the content with a
       ** newline.  If we're already doing multiline content, that extra
       ** newline (if it exists) is already there.
       */

       if (!*stack)
       {
              fprintf(signed_content_fp, "\r\n");
       }

       if (fflush(signed_content_fp) < 0 || ferror(signed_content_fp))
       {
              fclose(signed_content_fp);
              return (-1);
       }

       boundary=get_boundary(*stack, "", signed_content_fp);

       if (my_rewind(signed_content_fp) < 0)
       {
              fclose(signed_content_fp);
              return (-1);
       }

#define C(s) (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S(s) (*output_func)( s, strlen(s), output_func_arg)

       C("Content-Type: multipart/signed;\n"
         "    boundary=\"");
       S(boundary);
       C("\";\n"
         "    micalg=pgp-sha1;"
         " protocol=\"application/pgp-signature\"\n"
         "\n"
         "This is a MIME GnuPG-signed message.  If you see this text, it means that\n"
         "your E-mail or Usenet software does not support MIME signed messages.\n"
         "The Internet standard for MIME PGP messages, RFC 2015, was published in 1996.\n"
         "To open this message correctly you will need to install E-mail or Usenet\n"
         "software that supports modern Internet standards.\n"
         "\n--");
       S(boundary);
       C("\n");


       gfoi.output_func=output_func;
       gfoi.output_func_arg=output_func_arg;
       gfoi.gpgptr= &gpg;

       if (libmail_gpgmime_forksignencrypt(gpghome, passphrase_fd,
                                       GPG_SE_SIGN,
                                       argc, argv,
                                       &gpg_fork_output, &gfoi,
                                       &gpg))
       {
              fclose(signed_content_fp);
              return (-1);
       }

       while (fgets(buf, sizeof(buf), signed_content_fp) != NULL)
       {
              char *p;
              size_t j, k;

              libmail_gpgmime_write(&gpg, buf, strlen(buf));

              p=buf;
              for (j=k=0; p[j]; j++)
                     if (p[j] != '\r')
                            p[k++]=p[j];

              if (k)
                     (*output_func)(p, k, output_func_arg);
       }

       C("\n--");
       S(boundary);

       C("\n"
         "Content-Type: application/pgp-signature\n"
         "Content-Transfer-Encoding: 7bit\n\n");

#undef C
#undef S

       if (libmail_gpgmime_finish(&gpg))
              rc= -1; /* TODO */

       if (rc)
       {
              (*errhandler)(libmail_gpgmime_getoutput(&gpg),
                           errhandler_arg);
              fclose(signed_content_fp);
              return -1;
       }

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(boundary, strlen(boundary), output_func_arg);
       (*output_func)("--\n", 3, output_func_arg);

       fclose(signed_content_fp);
       if (*iseof)
              return 0;

       (*output_func)("\n--", 3, output_func_arg);
       (*output_func)(b->boundary, strlen(b->boundary), output_func_arg);
       if (clos_flag)
              (*output_func)("--", 2, output_func_arg);
       (*output_func)("\n", 1, output_func_arg);

       if (clos_flag)
       {
              libmail_mimestack_pop_to(stack, b);
              find_boundary(stack, iseof, input_func, input_func_arg,
                           output_func, output_func_arg, 1);
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dosignencode ( int  dosign,
int  doencode,
int  dodecode,
const char *  gpghome,
const char *  passphrase_fd,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
void(*)(const char *, void *)  errhandler_func,
void *  errhandler_arg,
int  argc,
char **  argv,
int *  status 
) [static]

Definition at line 1998 of file gpg.c.

{
       char temp_decode_name[TEMPNAMEBUFSIZE];
       int fdin;
       int fdout;
       FILE *fdin_fp;
       char buffer[8192];
       struct rfc2045src *src;
       struct rfc2045 *rfcp;
       int rc;

       if (!dosign || doencode)
              return dosignencode2(dosign, doencode, dodecode,
                                 gpghome,
                                 passphrase_fd,
                                 input_func,
                                 input_func_arg,
                                 output_func,
                                 output_func_arg,
                                 errhandler_func,
                                 errhandler_arg,
                                 argc, argv, status);

       /* Save the message into a temp file, first */

       fdin=libmail_tempfile(temp_decode_name);

       if (fdin < 0 ||
           (fdin_fp=fdopen(fdin, "w+")) == NULL)
       {
              if (fdin >= 0)
                     close(fdin);

              (*errhandler_func)("Cannot create temporary file",
                               errhandler_arg);
              return (-1);
       }

       unlink(temp_decode_name);

       if (!(rfcp=rfc2045_alloc_ac()))
       {
              (*errhandler_func)(strerror(errno), errhandler_arg);
              fclose(fdin_fp);
              return (-1);
       }

       while ( (*input_func)(buffer, sizeof(buffer), input_func_arg) == 0)
       {
              size_t l=strlen(buffer);

              if (fwrite(buffer, l, 1, fdin_fp) != 1)
              {
                     (*errhandler_func)(strerror(errno), errhandler_arg);
                     fclose(fdin_fp);
                     rfc2045_free(rfcp);
                     return (-1);
              }

              /* Parse the message at the same time it's being saved */

              rfc2045_parse(rfcp, buffer, l);
       }

       if (fseek(fdin_fp, 0L, SEEK_SET) < 0)
       {
              (*errhandler_func)(strerror(errno), errhandler_arg);
              fclose(fdin_fp);
              rfc2045_free(rfcp);
              return (-1);
       }

       if (!rfc2045_ac_check(rfcp, RFC2045_RW_7BIT))
       {
              rfc2045_free(rfcp);

              /* No need to rewrite, just do this */

              rc=dosignencode2(dosign, doencode, dodecode,
                                 gpghome,
                                 passphrase_fd,
                                 input_func_from_fp,
                                 fdin_fp,
                                 output_func,
                                 output_func_arg,
                                 errhandler_func,
                                 errhandler_arg,
                                 argc, argv, status);

              fclose(fdin_fp);

              return rc;
       }

       /* Rewrite the message into another temp file */

       fdout=libmail_tempfile(temp_decode_name);

       src=rfc2045src_init_fd(fileno(fdin_fp));

       if (fdout < 0 || src == NULL ||
           rfc2045_rewrite(rfcp, src, fdout, "mimegpg") < 0 ||
           lseek(fdout, 0L, SEEK_SET) < 0)
       {
              if (fdout >= 0)
                     close(fdout);
              if (src)
                     rfc2045src_deinit(src);

              (*errhandler_func)(strerror(errno), errhandler_arg);
              rfc2045_free(rfcp);
              fclose(fdin_fp);
              return (-1);
       }
       fclose(fdin_fp);
       rfc2045_free(rfcp);
       rfc2045src_deinit(src);

       /* Now, read the converted message, from the temp file */

       if ((fdin_fp=fdopen(fdout, "w+")) == NULL)
       {
              close(fdout);

              (*errhandler_func)("Cannot create temporary file",
                               errhandler_arg);
              return (-1);
       }

       rc=dosignencode2(dosign, doencode, dodecode,
                      gpghome,
                      passphrase_fd,
                      input_func_from_fp,
                      fdin_fp,
                      output_func,
                      output_func_arg,
                      errhandler_func,
                      errhandler_arg,
                      argc, argv, status);
       fclose(fdin_fp);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dosignencode2 ( int  dosign,
int  doencode,
int  dodecode,
const char *  gpghome,
const char *  passphrase_fd,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
void(*)(const char *, void *)  errhandler_func,
void *  errhandler_arg,
int  argc,
char **  argv,
int *  status 
) [static]

Definition at line 780 of file gpg.c.

{
       struct mimestack *boundary_stack=0;
       int iseof=0;

       *status=0;

       while (!iseof)
       {
              int errflag;

              static const char ct_s[]="content-type:";
              struct header *h=read_headers(&boundary_stack, &iseof,
                                         input_func, input_func_arg,
                                         output_func,
                                         output_func_arg,
                                         dodecode ? 0:1,
                                         &errflag),
                     *hct;

              if (errflag)
                     return 1;

              if (iseof && !h)
                     continue;     /* Artifact */

              hct=libmail_header_find(h, ct_s);

              /*
              ** If this is a multipart MIME section, we can keep on
              ** truckin'.
              **
              */

              if (hct)
              {
                     struct mime_header *mh=
                            libmail_mimeheader_parse(hct->header+
                                                  (sizeof(ct_s)-1));
                     const char *bv;

                     if (!mh)
                     {
                            libmail_header_free(h);
                            return (-1);
                     }

                     if (strcasecmp(mh->header_name, "multipart/x-mimegpg")
                         == 0)
                     {
                            /* Punt */

                            char *buf=malloc(strlen(hct->header)+100);
                            const char *p;

                            if (!buf)
                            {
                                   libmail_mimeheader_free(mh);
                                   libmail_header_free(h);
                                   return (-1);
                            }
                            strcpy(buf, "Content-Type: multipart/mixed");
                            p=strchr(hct->header, ';');
                            strcat(buf, p ? p:"");
                            free(hct->header);
                            hct->header=buf;

                            libmail_mimeheader_free(mh);
                            mh=libmail_mimeheader_parse(hct->header+
                                                     sizeof(ct_s)-1);
                            if (!mh)
                            {
                                   libmail_header_free(h);
                                   return (-1);
                            }
                     }

                     if (strncasecmp(mh->header_name, "multipart/", 10)==0
                         && (bv=libmail_mimeheader_getattr(mh, "boundary")) != 0

                         && (doencode & LIBMAIL_GPG_ENCAPSULATE) == 0

                         && !dosign
                         )
                     {
                            struct header *p;

                            if (libmail_mimestack_push(&boundary_stack,
                                                    bv) < 0)
                            {
                                   libmail_header_free(h);
                                   return (-1);
                            }

                            if (dodecode)
                            {
                                   int rc;

                                   if (strcasecmp(mh->header_name,
                                                 "multipart/signed")==0
                                       && (dodecode & LIBMAIL_GPG_CHECKSIGN)
                                       && isgpg(mh))
                                   {
                                          int errflag;

                                          print_noncontent_headers(h,
                                                                output_func,
                                                                output_func_arg
                                                                );
                                          libmail_mimeheader_free(mh);
                                          rc=checksign(gpghome,
                                                      passphrase_fd,
                                                      &boundary_stack,
                                                      &iseof,
                                                      h,
                                                      input_func,
                                                      input_func_arg,
                                                      output_func,
                                                      output_func_arg,
                                                      argc, argv,
                                                      &errflag);
                                          libmail_header_free(h);

                                          if (errflag)
                                                 *status |=
                                                        LIBMAIL_ERR_VERIFYSIG;
                                          if (rc)
                                                 return -1;

                                          continue;
                                   }

                                   if (strcasecmp(mh->header_name,
                                                 "multipart/encrypted")
                                       ==0
                                       && (dodecode & LIBMAIL_GPG_UNENCRYPT)
                                       && isgpg(mh))
                                   {
                                          int errflag;

                                          print_noncontent_headers(h,
                                                                output_func,
                                                                output_func_arg
                                                                );
                                          libmail_mimeheader_free(mh);
                                          rc=decrypt(gpghome,
                                                    passphrase_fd,
                                                    &boundary_stack,
                                                    &iseof,
                                                    h,
                                                    input_func,
                                                    input_func_arg,
                                                    output_func,
                                                    output_func_arg,
                                                    argc, argv,
                                                    &errflag);
                                          libmail_header_free(h);

                                          if (errflag)
                                                 *status |=
                                                        LIBMAIL_ERR_DECRYPT;
                                          if (rc)
                                                 return -1;
                                          continue;
                                   }
                            }

                            for (p=h; p; p=p->next)
                            {
                                   (*output_func)(p->header,
                                                 strlen(p->header),
                                                 output_func_arg);
                            }

                            (*output_func)("\n", 1, output_func_arg);
                            libmail_header_free(h);
                            libmail_mimeheader_free(mh);

                            find_boundary(&boundary_stack, &iseof,
                                         input_func,
                                         input_func_arg,
                                         output_func,
                                         output_func_arg, dodecode ? 0:1);
                            continue;
                     }
                     libmail_mimeheader_free(mh);
              }

              if (dodecode)
              {
                     struct header *p;
                     int is_message_rfc822=0;

                     for (p=h; p; p=p->next)
                     {
                            (*output_func)(p->header,
                                          strlen(p->header),
                                          output_func_arg);
                     }
                     (*output_func)("\n", 1, output_func_arg);

                     /*
                     ** If this is a message/rfc822 attachment, we can
                     ** resume reading the next set of headers.
                     */

                     hct=libmail_header_find(h, ct_s);
                     if (hct)
                     {
                            struct mime_header *mh=
                                   libmail_mimeheader_parse(hct->header+
                                                         (sizeof(ct_s)
                                                          -1));
                            if (!mh)
                            {
                                   libmail_header_free(h);
                                   return (-1);
                            }

                            if (strcasecmp(mh->header_name,
                                          "message/rfc822") == 0)
                                   is_message_rfc822=1;
                            libmail_mimeheader_free(mh);
                     }
                     libmail_header_free(h);

                     if (!is_message_rfc822)
                            find_boundary(&boundary_stack, &iseof,
                                         input_func,
                                         input_func_arg,
                                         output_func,
                                         output_func_arg, 0);
                     continue;
              }

              if (doencode ?
                  dogpgencrypt(gpghome,
                             passphrase_fd,
                             &boundary_stack, h, &iseof,
                             input_func,
                             input_func_arg,
                             output_func,
                             output_func_arg,
                             argc, argv, dosign,
                             errhandler_func, errhandler_arg)
                  :
                  dogpgsign(gpghome,
                           passphrase_fd,
                           &boundary_stack, h, &iseof,
                           input_func,
                           input_func_arg,
                           output_func,
                           output_func_arg,
                           argc, argv,
                           errhandler_func, errhandler_arg))
              {
                     libmail_header_free(h);
                     return 1;
              }

              libmail_header_free(h);
       }

       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dumpdecrypt ( const char *  c,
size_t  n,
void *  vp 
) [static]

Definition at line 1852 of file gpg.c.

{
       FILE *fp=(FILE *)vp;

       if (n == 0)
              return 0;

       if (fwrite(c, n, 1, fp) != 1)
              return -1;
       return (0);
}

Here is the caller graph for this function:

static int encode_header ( const char *  h) [static]

Definition at line 281 of file gpg.c.

{
       if (strncasecmp(h, "content-", 8) == 0)
              return (1);
       return (0);
}

Here is the caller graph for this function:

static const char* encoding_str ( const char *  p) [static]

Definition at line 1438 of file gpg.c.

{
       while (*p)
       {
              if (*p <= 0 || *p >= 0x7F)
                     return ("8bit");
              ++p;
       }
       return ("7bit");
}

Here is the caller graph for this function:

static void find_boundary ( struct mimestack **  stack,
int *  iseof,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  doappend 
) [static]

Definition at line 115 of file gpg.c.

{
       char buf[BUFSIZ];

       for (;;)
       {
              int is_closing;
              struct mimestack *b;

              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     return;
              }

              if (!(b=is_boundary(*stack, buf, &is_closing)))
              {
                     if (output_func)
                            (*output_func)(buf, strlen(buf),
                                          output_func_arg);

                     while (strchr(buf, '\n') == 0)
                     {
                            if ( (*input_func)(buf, sizeof(buf),
                                             input_func_arg))
                            {
                                   *iseof=1;
                                   return;
                            }
                            if (output_func)
                                   (*output_func)(buf, strlen(buf),
                                                 output_func_arg);
                     }
                     continue;
              }

              if (output_func)
              {
                     (*output_func)("--", 2, output_func_arg);
                     (*output_func)(b->boundary, strlen(b->boundary),
                                   output_func_arg);

                     if (is_closing)
                            (*output_func)("--", 2, output_func_arg);

                     (*output_func)("\n", 1, output_func_arg);
              }

              if (is_closing)
              {
                     libmail_mimestack_pop_to(stack, b);
                     continue;
              }
              break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char * get_boundary ( struct mimestack m,
const char *  errmsg,
FILE *  fp 
) [static]

Definition at line 1425 of file gpg.c.

{
       const char *p;

       do
       {
              p=newboundary();
       } while (!good_boundary(p, m, errmsg, fp));
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int good_boundary ( const char *  boundary,
struct mimestack m,
const char *  errmsg,
FILE *  fp 
) [static]

Definition at line 1388 of file gpg.c.

{
       int dummy;
       int l=strlen(boundary);
       const char *p;
       char buf[BUFSIZ];

       if (is_boundary(m, boundary, &dummy))
              return (0);

       for (p=errmsg; *p; )
       {
              if (*p == '-' && p[1] == '-' && strncasecmp(p+2, boundary, l)
                  == 0)
                     return (0);

              while (*p)
                     if (*p++ == '\n')
                            break;
       }

       if (fp)
       {
              if (my_rewind(fp) < 0)
                     return 0;

              while (fgets(buf, sizeof(buf), fp))
              {
                     if (buf[0] == '-' && buf[1] == '-' &&
                         strncasecmp(buf+2, boundary, l) == 0)
                            return (0);
              }
       }
       return (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gpg_fork_output ( const char *  p,
size_t  n,
void *  dummy 
) [static]

Definition at line 294 of file gpg.c.

{
       struct gpg_fork_output_info *info=(struct gpg_fork_output_info *)dummy;

       (*info->output_func)(p, n, info->output_func_arg);
       return 0;
}

Here is the caller graph for this function:

static int input_func_from_fp ( char *  buf,
size_t  cnt,
void *  vp 
) [static]

Definition at line 1985 of file gpg.c.

{
       if (fgets(buf, cnt, (FILE *)vp) == NULL)
              return (-1);
       return (0);
}

Here is the caller graph for this function:

static struct mimestack* is_boundary ( struct mimestack s,
const char *  line,
int *  isclosing 
) [static, read]

Definition at line 91 of file gpg.c.

{
       struct mimestack *b;

       if (line[0] != '-' || line[1] != '-' ||
           (b=libmail_mimestack_search(s, line+2)) == 0)
              return (NULL);


       *isclosing=strncmp(line+2+strlen(b->boundary), "--", 2) == 0;
       return (b);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int isgpg ( struct mime_header mh) [static]

Definition at line 1059 of file gpg.c.

{
       const char *attr;

       attr=libmail_mimeheader_getattr(mh, "protocol");

       if (!attr)
              return (0);

       if (strcasecmp(attr, "application/pgp-encrypted") == 0)
              return (1);

       if (strcasecmp(attr, "application/pgp-signature") == 0)
       {
              return (1);
       }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int libmail_gpg_decode ( int  mode,
struct libmail_gpg_info options 
)

Definition at line 2198 of file gpg.c.

{
       int rc;
       struct libmail_gpg_errhandler eh;

       eh.options=options;
       eh.err_flag=0;

       if ((mode & (LIBMAIL_GPG_UNENCRYPT|LIBMAIL_GPG_CHECKSIGN)) == 0)
       {
              (*options->errhandler_func)("Invalid arguments to"
                                       " libmail_gpg_decode",
                                       options->errhandler_arg);
              return -1;
       }

       rc=dosignencode(0, 0, mode,
                     options->gnupghome,
                     options->passphrase_fd,
                     options->input_func,
                     options->input_func_arg,
                     options->output_func,
                     options->output_func_arg,
                     &libmail_gpg_errfunc,
                     &eh,
                     options->argc,
                     options->argv,
                     &options->errstatus);

       if (rc && !eh.err_flag)
              (*options->errhandler_func)(strerror(errno),
                                       options->errhandler_arg);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void libmail_gpg_errfunc ( const char *  errmsg,
void *  vp 
) [static]

Definition at line 1972 of file gpg.c.

{
       struct libmail_gpg_errhandler *eh=(struct libmail_gpg_errhandler *)vp;

       if (!eh->err_flag)
       {
              eh->err_flag=1;

              (*eh->options->errhandler_func)(errmsg,
                                          eh->options->errhandler_arg);
       }
}

Here is the caller graph for this function:

int libmail_gpg_inputfunc_readfp ( char *  buf,
size_t  cnt,
void *  vp 
)

Definition at line 48 of file gpg.c.

{
       FILE *fp=(FILE *)vp;
       size_t i;
       int c;

       if (cnt == 0)
              return -1;

       --cnt;

       for (i=0; i<cnt; i++)
       {
              if ((c=getc(fp)) == EOF)
              {
                     if (i == 0)
                            return -1;
                     break;
              }
              buf[i]=c;

              if (c == '\n')
              {
                     ++i;
                     break;
              }
       }
       buf[i]=0;
       return 0;
}
void libmail_gpg_noexec ( int  fd)

Definition at line 79 of file gpg.c.

{
#ifdef FD_CLOEXEC
       fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
}

Here is the caller graph for this function:

int libmail_gpg_signencode ( int  dosign,
int  doencode,
struct libmail_gpg_info options 
)

Definition at line 2153 of file gpg.c.

{
       int rc;
       struct libmail_gpg_errhandler eh;

       eh.options=options;
       eh.err_flag=0;

       if (doencode != LIBMAIL_GPG_INDIVIDUAL &&
           doencode != LIBMAIL_GPG_ENCAPSULATE)
              doencode=0;

       if (!dosign && !doencode)
       {
              (*options->errhandler_func)("Invalid arguments to"
                                       " libmail_gpg_signencode",
                                       options->errhandler_arg);
              return -1;
       }

       rc=dosignencode(dosign, doencode, 0,
                     options->gnupghome,
                     options->passphrase_fd,
                     options->input_func,
                     options->input_func_arg,
                     options->output_func,
                     options->output_func_arg,
                     &libmail_gpg_errfunc,
                     &eh,
                     options->argc,
                     options->argv,
                     &options->errstatus);

       if (rc && !eh.err_flag)
              (*options->errhandler_func)(strerror(errno),
                                       options->errhandler_arg);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int my_rewind ( FILE *  fp) [static]

Definition at line 40 of file gpg.c.

{
       if (fflush(fp) || ferror(fp) || fseek(fp, 0L, SEEK_SET))
              return (-1);
       clearerr(fp);
       return (0);
}

Here is the caller graph for this function:

static const char* newboundary ( ) [static]

Definition at line 1370 of file gpg.c.

{
       static char buffer[256];
       static unsigned counter=0;
       time_t t;
       char hostnamebuf[256];

       time(&t);
       hostnamebuf[sizeof(hostnamebuf)-1]=0;
       if (gethostname(hostnamebuf, sizeof(hostnamebuf)-1) < 0)
              hostnamebuf[0]=0;

       sprintf(buffer, "=_%-1.30s-%u-%u-%04u",
              hostnamebuf, (unsigned)getpid(),
              (unsigned)t, ++counter);
       return (buffer);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int nybble ( char  c) [static]

Definition at line 1078 of file gpg.c.

{
       static const char x[]="0123456789ABCDEFabcdef";

       const char *p=strchr(x, c);
       int n;

       if (!p) p=x;

       n= p-x;
       if (n >= 16)
              n -= 6;
       return (n);
}

Here is the caller graph for this function:

static void open_result_multipart ( void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  rc,
const char *  new_boundary,
const char *  err_str,
const char *  err_charset 
) [static]

Definition at line 1539 of file gpg.c.

{
#define C(s) (*output_func)( s, sizeof(s)-1, output_func_arg)
#define S(s) (*output_func)( s, strlen(s), output_func_arg)

       char n[10];
       const char *p;

       sprintf(n, "%d", rc);

       C("Content-Type: multipart/x-mimegpg; xpgpstatus=");

       S(n);

       C("; boundary=\"");

       S(new_boundary);

       C("\"\n"
         "\nThis is a MIME GnuPG-processed message.  If you see this text, it means\n"
         "that your E-mail or Usenetsoftware does not support MIME-formatted messages.\n\n"
         "--");

       S(new_boundary);
       C("\nContent-Type: text/x-gpg-output; charset=");
       S(err_charset);
       C("\nContent-Transfer-Encoding: ");

       p=encoding_str(err_str);
       S(p);
       C("\n\n");
       S(err_str);
#undef C
#undef S
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_noncontent_headers ( struct header h,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg 
) [static]

Definition at line 764 of file gpg.c.

{
       struct header *p;

       for (p=h; p; p=p->next)
       {
              if (strncasecmp(p->header, "content-", 8) == 0)
                     continue;
              (*output_func)(p->header, strlen(p->header), output_func_arg);
       }
}

Here is the caller graph for this function:

static struct header* read_headers ( struct mimestack **  stack,
int *  iseof,
int(*)(char *, size_t, void *vp)  input_func,
void *  input_func_arg,
void(*)(const char *, size_t, void *)  output_func,
void *  output_func_arg,
int  doappend,
int *  errflag 
) [static, read]

Definition at line 184 of file gpg.c.

{
       char buf[BUFSIZ];
       struct read_header_context rhc;
       struct header *h;

       *errflag=0;
       libmail_readheader_init(&rhc);

       while (!*iseof)
       {
              if ( (*input_func)(buf, sizeof(buf), input_func_arg))
              {
                     *iseof=1;
                     break;
              }

              if (READ_START_OF_LINE(rhc))
              {
                     struct mimestack *b;
                     int is_closing;

                     if (strcmp(buf, "\n") == 0
                         || strcmp(buf, "\r\n") == 0)
                            break;

                     b=is_boundary(*stack, buf, &is_closing);

                     if (b)
                     {
                            /*
                            ** Corrupted MIME message.  We should NOT
                            ** see a MIME boundary in the middle of the
                            ** headers!
                            **
                            ** Ignore this damage.
                            */

                            struct header *p;

                            h=libmail_readheader_finish(&rhc);

                            for (p=h; p; p=p->next)
                                   (*output_func)(p->header,
                                                 strlen(p->header),
                                                 output_func_arg);

                            (*output_func)("--", 2, output_func_arg);
                            (*output_func)(b->boundary,
                                          strlen(b->boundary),
                                          output_func_arg);

                            if (is_closing)
                                   (*output_func)("--", 2,
                                                 output_func_arg);

                            (*output_func)("\n", 1, output_func_arg);

                            if (is_closing)
                            {
                                   libmail_mimestack_pop_to(stack, b);
                                   find_boundary(stack, iseof,
                                                input_func,
                                                input_func_arg,
                                                output_func,
                                                output_func_arg,
                                                doappend);
                            }
                            libmail_header_free(h);

                            libmail_readheader_init(&rhc);
                            continue; /* From the top */
                     }
              }
              if (libmail_readheader(&rhc, buf) < 0)
              {
                     libmail_header_free(libmail_readheader_finish(&rhc));
                     *errflag= -1;
                     return NULL;
              }
       }

       return (libmail_readheader_finish(&rhc));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_temp_fp ( const char *  p,
size_t  n,
void *  vp 
) [static]

Definition at line 1624 of file gpg.c.

{
       if (fwrite(p, n, 1, (FILE *)vp) != 1)
              ; /* ignored */
}

Here is the caller graph for this function: