1b47612bd5f86f6d475010028d460ea01a91d3c3
[gnupg.git] / tools / wks-util.c
1 /* wks-utils.c - Common helper fucntions for wks tools
2  * Copyright (C) 2016 g10 Code GmbH
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "util.h"
26 #include "mime-maker.h"
27 #include "send-mail.h"
28 #include "gpg-wks.h"
29
30
31 /* Helper to write mail to the output(s).  */
32 gpg_error_t
33 wks_send_mime (mime_maker_t mime)
34 {
35   gpg_error_t err;
36   estream_t mail;
37
38   /* Without any option we take a short path.  */
39   if (!opt.use_sendmail && !opt.output)
40     return mime_maker_make (mime, es_stdout);
41
42   mail = es_fopenmem (0, "w+b");
43   if (!mail)
44     {
45       err = gpg_error_from_syserror ();
46       return err;
47     }
48
49   err = mime_maker_make (mime, mail);
50
51   if (!err && opt.output)
52     {
53       es_rewind (mail);
54       err = send_mail_to_file (mail, opt.output);
55     }
56
57   if (!err && opt.use_sendmail)
58     {
59       es_rewind (mail);
60       err = send_mail (mail);
61     }
62
63   es_fclose (mail);
64   return err;
65 }
66
67
68 /* Parse the policy flags by reading them from STREAM and storing them
69  * into FLAGS.  If IGNORE_UNKNOWN is iset unknown keywords are
70  * ignored.  */
71 gpg_error_t
72 wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
73 {
74   enum tokens {
75     TOK_MAILBOX_ONLY,
76     TOK_DANE_ONLY,
77     TOK_AUTH_SUBMIT,
78     TOK_MAX_PENDING
79   };
80   static struct {
81     const char *name;
82     enum tokens token;
83   } keywords[] = {
84     { "mailbox-only", TOK_MAILBOX_ONLY },
85     { "dane-only",    TOK_DANE_ONLY    },
86     { "auth-submit",  TOK_AUTH_SUBMIT  },
87     { "max-pending",  TOK_MAX_PENDING  }
88   };
89   gpg_error_t err = 0;
90   int lnr = 0;
91   char line[1024];
92   char *p, *keyword, *value;
93   int i, n;
94
95   memset (flags, 0, sizeof *flags);
96
97   while (es_fgets (line, DIM(line)-1, stream) )
98     {
99       lnr++;
100       n = strlen (line);
101       if (!n || line[n-1] != '\n')
102         {
103           err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
104                            : GPG_ERR_INCOMPLETE_LINE);
105           break;
106         }
107       trim_trailing_spaces (line);
108       /* Skip empty and comment lines. */
109       for (p=line; spacep (p); p++)
110         ;
111       if (!*p || *p == '#')
112         continue;
113
114       if (*p == ':')
115         {
116           err = gpg_error (GPG_ERR_SYNTAX);
117           break;
118         }
119
120       keyword = p;
121       value = NULL;
122       if ((p = strchr (p, ':')))
123         {
124           /* Colon found: Keyword with value.  */
125           *p++ = 0;
126           for (; spacep (p); p++)
127             ;
128           if (!*p)
129             {
130               err = gpg_error (GPG_ERR_MISSING_VALUE);
131               break;
132             }
133           value = p;
134         }
135
136       for (i=0; i < DIM (keywords); i++)
137         if (!ascii_strcasecmp (keywords[i].name, keyword))
138           break;
139       if (!(i < DIM (keywords)))
140         {
141           if (ignore_unknown)
142             continue;
143           err = gpg_error (GPG_ERR_INV_NAME);
144           break;
145         }
146
147       switch (keywords[i].token)
148         {
149         case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break;
150         case TOK_DANE_ONLY:    flags->dane_only = 1;    break;
151         case TOK_AUTH_SUBMIT:  flags->auth_submit = 1;  break;
152         case TOK_MAX_PENDING:
153           if (!value)
154             {
155               err = gpg_error (GPG_ERR_SYNTAX);
156               goto leave;
157             }
158           /* FIXME: Define whether these are seconds, hours, or days
159            * and decide whether to allow other units.  */
160           flags->max_pending = atoi (value);
161           break;
162         }
163     }
164
165   if (!err && !es_feof (stream))
166     err = gpg_error_from_syserror ();
167
168  leave:
169   if (err)
170     log_error ("error reading '%s', line %d: %s\n",
171                es_fname_get (stream), lnr, gpg_strerror (err));
172
173   return err;
174 }