Cleanup logging.
[apps/pfixtools.git] / postlicyd / query.c
1 /******************************************************************************/
2 /*          pfixtools: a collection of postfix related tools                  */
3 /*          ~~~~~~~~~                                                         */
4 /*  ________________________________________________________________________  */
5 /*                                                                            */
6 /*  Redistribution and use in source and binary forms, with or without        */
7 /*  modification, are permitted provided that the following conditions        */
8 /*  are met:                                                                  */
9 /*                                                                            */
10 /*  1. Redistributions of source code must retain the above copyright         */
11 /*     notice, this list of conditions and the following disclaimer.          */
12 /*  2. Redistributions in binary form must reproduce the above copyright      */
13 /*     notice, this list of conditions and the following disclaimer in the    */
14 /*     documentation and/or other materials provided with the distribution.   */
15 /*  3. The names of its contributors may not be used to endorse or promote    */
16 /*     products derived from this software without specific prior written     */
17 /*     permission.                                                            */
18 /*                                                                            */
19 /*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
20 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
21 /*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
22 /*  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS    */
23 /*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR    */
24 /*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
25 /*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
26 /*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
27 /*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
28 /*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
29 /*  THE POSSIBILITY OF SUCH DAMAGE.                                           */
30 /******************************************************************************/
31
32 /*
33  * Copyright © 2007 Pierre Habouzit
34  * Copyright © 2008 Florent Bruneau
35  */
36
37 #include "query.h"
38 #include "policy_tokens.h"
39
40 bool query_parse(query_t *query, char *p)
41 {
42 #define PARSE_CHECK(expr, error, ...)                                        \
43     do {                                                                     \
44         if (!(expr)) {                                                       \
45             err(error, ##__VA_ARGS__);                                       \
46             return false;                                                    \
47         }                                                                    \
48     } while (0)
49
50     p_clear(query, 1);
51     query->state = SMTP_UNKNOWN;
52     while (*p != '\n') {
53         char *k, *v;
54         int klen, vlen, vtk;
55
56         while (isblank(*p))
57             p++;
58         p = strchr(k = p, '=');
59         PARSE_CHECK(p, "could not find '=' in line");
60         for (klen = p - k; klen && isblank(k[klen]); klen--);
61         p += 1; /* skip = */
62
63         while (isblank(*p))
64             p++;
65         p = strchr(v = p, '\n');
66         PARSE_CHECK(p, "could not find final \\n in line");
67         for (vlen = p - v; vlen && isblank(v[vlen]); vlen--);
68         p += 1; /* skip \n */
69
70         vtk = policy_tokenize(v, vlen);
71         switch (policy_tokenize(k, klen)) {
72 #define CASE(up, low)  case PTK_##up: query->low = v; v[vlen] = '\0';  break;
73             CASE(HELO_NAME,           helo_name);
74             CASE(QUEUE_ID,            queue_id);
75             CASE(SENDER,              sender);
76             CASE(RECIPIENT,           recipient);
77             CASE(RECIPIENT_COUNT,     recipient_count);
78             CASE(CLIENT_ADDRESS,      client_address);
79             CASE(CLIENT_NAME,         client_name);
80             CASE(REVERSE_CLIENT_NAME, reverse_client_name);
81             CASE(INSTANCE,            instance);
82             CASE(SASL_METHOD,         sasl_method);
83             CASE(SASL_USERNAME,       sasl_username);
84             CASE(SASL_SENDER,         sasl_sender);
85             CASE(SIZE,                size);
86             CASE(CCERT_SUBJECT,       ccert_subject);
87             CASE(CCERT_ISSUER,        ccert_issuer);
88             CASE(CCERT_FINGERPRINT,   ccert_fingerprint);
89             CASE(ENCRYPTION_PROTOCOL, encryption_protocol);
90             CASE(ENCRYPTION_CIPHER,   encryption_cipher);
91             CASE(ENCRYPTION_KEYSIZE,  encryption_keysize);
92             CASE(ETRN_DOMAIN,         etrn_domain);
93             CASE(STRESS,              stress);
94 #undef CASE
95
96           case PTK_REQUEST:
97             PARSE_CHECK(vtk == PTK_SMTPD_ACCESS_POLICY,
98                         "unexpected `request' value: %.*s", vlen, v);
99             break;
100
101           case PTK_PROTOCOL_NAME:
102             PARSE_CHECK(vtk == PTK_SMTP || vtk == PTK_ESMTP,
103                         "unexpected `protocol_name' value: %.*s", vlen, v);
104             query->esmtp = vtk == PTK_ESMTP;
105             break;
106
107           case PTK_PROTOCOL_STATE:
108             switch (vtk) {
109 #define CASE(name)  case PTK_##name: query->state = SMTP_##name; break;
110                 CASE(CONNECT);
111                 CASE(EHLO);
112                 CASE(HELO);
113                 CASE(MAIL);
114                 CASE(RCPT);
115                 CASE(DATA);
116                 CASE(END_OF_MESSAGE);
117                 CASE(VRFY);
118                 CASE(ETRN);
119               default:
120                 PARSE_CHECK(false, "unexpected `protocol_state` value: %.*s",
121                             vlen, v);
122 #undef CASE
123             }
124             break;
125
126           default:
127             warn("unexpected key, skipped: %.*s", klen, k);
128             continue;
129         }
130     }
131
132     return query->state != SMTP_UNKNOWN;
133 #undef PARSE_CHECK
134 }
135