~ubuntu-branches/ubuntu/saucy/postfix/saucy

« back to all changes in this revision

Viewing changes to src/tls/tls_proxy_clnt.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2011-02-22 11:20:43 UTC
  • mfrom: (1.1.27 upstream)
  • Revision ID: james.westby@ubuntu.com-20110222112043-c34ht219w3ybrilr
Tags: 2.8.0-2
* a little more lintian cleanup
* Fix missing format strings in smtp-sink.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      tlsproxy_clnt 3
 
4
/* SUMMARY
 
5
/*      postscreen TLS proxy support
 
6
/* SYNOPSIS
 
7
/*      #include <tlsproxy_clnt.h>
 
8
/*
 
9
/*      VSTREAM *tls_proxy_open(service, flags, peer_stream, peer_addr,
 
10
/*                                peer_port, timeout)
 
11
/*      const char *service;
 
12
/*      int     flags;
 
13
/*      VSTREAM *peer_stream;
 
14
/*      const char *peer_addr;
 
15
/*      const char *peer_port;
 
16
/*      int     timeout;
 
17
/*
 
18
/*      TLS_SESS_STATE *tls_proxy_context_receive(proxy_stream)
 
19
/*      VSTREAM *proxy_stream;
 
20
/*
 
21
/*      void    tls_proxy_context_free(tls_context)
 
22
/*      TLS_SESS_STATE *tls_context;
 
23
/* DESCRIPTION
 
24
/*      tls_proxy_open() prepares for inserting the tlsproxy(8)
 
25
/*      daemon between the current process and a remote peer (the
 
26
/*      actual insert operation is described in the next paragraph).
 
27
/*      The result value is a null pointer on failure. The peer_stream
 
28
/*      is not closed.  The resulting proxy stream is single-buffered.
 
29
/*
 
30
/*      After this, it is a good idea to use the VSTREAM_CTL_SWAP_FD
 
31
/*      request to swap the file descriptors between the plaintext
 
32
/*      peer_stream and the proxy stream from tls_proxy_open().
 
33
/*      This avoids the loss of application-configurable VSTREAM
 
34
/*      attributes on the plaintext peer_stream (such as longjmp
 
35
/*      buffer, timeout, etc.). Once the file descriptors are
 
36
/*      swapped, the proxy stream should be closed.
 
37
/*
 
38
/*      tls_proxy_context_receive() receives the TLS context object
 
39
/*      for the named proxy stream. This function must be called
 
40
/*      only if the TLS_PROXY_SEND_CONTEXT flag was specified in
 
41
/*      the tls_proxy_open() call. Note that this TLS context object
 
42
/*      is not compatible with tls_session_free(). It must be given
 
43
/*      to tls_proxy_context_free() instead.
 
44
/*
 
45
/*      After this, the proxy_stream is ready for plain-text I/O.
 
46
/*
 
47
/*      tls_proxy_context_free() destroys a TLS context object that
 
48
/*      was received with tls_proxy_context_receive().
 
49
/*
 
50
/*      Arguments:
 
51
/* .IP service
 
52
/*      The (base) name of the tlsproxy service.
 
53
/* .IP flags
 
54
/*      Bit-wise OR of:
 
55
/* .RS
 
56
/* .IP TLS_PROXY_FLAG_ROLE_SERVER
 
57
/*      Request the TLS server proxy role.
 
58
/* .IP TLS_PROXY_FLAG_ROLE_CLIENT
 
59
/*      Request the TLS client proxy role.
 
60
/* .IP TLS_PROXY_FLAG_SEND_CONTEXT
 
61
/*      Send the TLS context object.
 
62
/* .RE
 
63
/* .IP peer_stream
 
64
/*      Stream that connects the current process to a remote peer.
 
65
/* .IP peer_addr
 
66
/*      Printable IP address of the remote peer_stream endpoint.
 
67
/* .IP peer_port
 
68
/*      Printable TCP port of the remote peer_stream endpoint.
 
69
/* .IP timeout
 
70
/*      Time limit that the tlsproxy(8) daemon should use.
 
71
/* .IP proxy_stream
 
72
/*      Stream from tls_proxy_open().
 
73
/* .IP tls_context
 
74
/*      TLS session object from tls_proxy_context_receive().
 
75
/* LICENSE
 
76
/* .ad
 
77
/* .fi
 
78
/*      The Secure Mailer license must be distributed with this software.
 
79
/* AUTHOR(S)
 
80
/*      Wietse Venema
 
81
/*      IBM T.J. Watson Research
 
82
/*      P.O. Box 704
 
83
/*      Yorktown Heights, NY 10598, USA
 
84
/*--*/
 
85
 
 
86
#ifdef USE_TLS
 
87
 
 
88
/* System library. */
 
89
 
 
90
#include <sys_defs.h>
 
91
 
 
92
/* Utility library. */
 
93
 
 
94
#include <msg.h>
 
95
#include <mymalloc.h>
 
96
#include <connect.h>
 
97
#include <stringops.h>
 
98
#include <vstring.h>
 
99
 
 
100
/* Global library. */
 
101
 
 
102
#include <mail_proto.h>
 
103
#include <mail_params.h>
 
104
 
 
105
/* TLS library-specific. */
 
106
 
 
107
#include <tls.h>
 
108
#include <tls_proxy.h>
 
109
 
 
110
#define TLSPROXY_INIT_TIMEOUT           10
 
111
 
 
112
/* SLMs. */
 
113
 
 
114
#define STR     vstring_str
 
115
 
 
116
/* tls_proxy_open - open negotiations with TLS proxy */
 
117
 
 
118
VSTREAM *tls_proxy_open(const char *service, int flags,
 
119
                                VSTREAM *peer_stream,
 
120
                                const char *peer_addr,
 
121
                                const char *peer_port,
 
122
                                int timeout)
 
123
{
 
124
    VSTREAM *tlsproxy_stream;
 
125
    int     status;
 
126
    int     fd;
 
127
    static VSTRING *tlsproxy_service = 0;
 
128
    static VSTRING *remote_endpt = 0;
 
129
 
 
130
    /*
 
131
     * Initialize.
 
132
     */
 
133
    if (tlsproxy_service == 0) {
 
134
        tlsproxy_service = vstring_alloc(20);
 
135
        remote_endpt = vstring_alloc(20);
 
136
    }
 
137
 
 
138
    /*
 
139
     * Connect to the tlsproxy(8) daemon.
 
140
     */
 
141
    vstring_sprintf(tlsproxy_service, "%s/%s", MAIL_CLASS_PRIVATE, service);
 
142
    if ((fd = LOCAL_CONNECT(STR(tlsproxy_service), BLOCKING,
 
143
                            TLSPROXY_INIT_TIMEOUT)) < 0) {
 
144
        msg_warn("connect to %s service: %m", STR(tlsproxy_service));
 
145
        return (0);
 
146
    }
 
147
 
 
148
    /*
 
149
     * Initial handshake. Send the data attributes now, and send the client
 
150
     * file descriptor in a later transaction.
 
151
     * 
 
152
     * XXX The formatted endpoint should be a state member. Then, we can
 
153
     * simplify all the format strings throughout the program.
 
154
     */
 
155
    tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
 
156
    vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port);
 
157
    attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
 
158
               ATTR_TYPE_STR, MAIL_ATTR_REMOTE_ENDPT, STR(remote_endpt),
 
159
               ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags,
 
160
               ATTR_TYPE_INT, MAIL_ATTR_TIMEOUT, timeout,
 
161
               ATTR_TYPE_END);
 
162
    if (vstream_fflush(tlsproxy_stream) != 0) {
 
163
        msg_warn("error sending request to %s service: %m",
 
164
                 STR(tlsproxy_service));
 
165
        vstream_fclose(tlsproxy_stream);
 
166
        return (0);
 
167
    }
 
168
 
 
169
    /*
 
170
     * Receive the "TLS is available" indication.
 
171
     * 
 
172
     * This may seem out of order, but we must have a read transaction between
 
173
     * sending the request attributes and sending the SMTP client file
 
174
     * descriptor. We can't assume UNIX-domain socket semantics here.
 
175
     */
 
176
    if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
 
177
                  ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
 
178
                  ATTR_TYPE_END) != 1 || status == 0) {
 
179
 
 
180
        /*
 
181
         * The TLS proxy reports that the TLS engine is not available (due to
 
182
         * configuration error, or other causes).
 
183
         */
 
184
        msg_warn("%s service role \"%s\" is not available",
 
185
                 STR(tlsproxy_service),
 
186
                 (flags & TLS_PROXY_FLAG_ROLE_SERVER) ? "server" :
 
187
                 (flags & TLS_PROXY_FLAG_ROLE_CLIENT) ? "client" :
 
188
                 "bogus role");
 
189
        vstream_fclose(tlsproxy_stream);
 
190
        return (0);
 
191
    }
 
192
 
 
193
    /*
 
194
     * Send the remote SMTP client file descriptor.
 
195
     */
 
196
    if (LOCAL_SEND_FD(vstream_fileno(tlsproxy_stream),
 
197
                      vstream_fileno(peer_stream)) < 0) {
 
198
 
 
199
        /*
 
200
         * Some error: drop the TLS proxy stream.
 
201
         */
 
202
        msg_warn("sending file handle to %s service: %m",
 
203
                 STR(tlsproxy_service));
 
204
        vstream_fclose(tlsproxy_stream);
 
205
        return (0);
 
206
    }
 
207
    return (tlsproxy_stream);
 
208
}
 
209
 
 
210
/* tls_proxy_context_receive - receive TLS session object from tlsproxy(8) */
 
211
 
 
212
TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *proxy_stream)
 
213
{
 
214
    TLS_SESS_STATE *tls_context;
 
215
 
 
216
    tls_context = (TLS_SESS_STATE *) mymalloc(sizeof(*tls_context));
 
217
 
 
218
    if (attr_scan(proxy_stream, ATTR_FLAG_STRICT,
 
219
               ATTR_TYPE_FUNC, tls_proxy_context_scan, (char *) tls_context,
 
220
                  ATTR_TYPE_END) != 1) {
 
221
        tls_proxy_context_free(tls_context);
 
222
        return (0);
 
223
    } else {
 
224
        return (tls_context);
 
225
    }
 
226
}
 
227
 
 
228
/* tls_proxy_context_free - destroy object from tls_proxy_context_receive() */
 
229
 
 
230
void    tls_proxy_context_free(TLS_SESS_STATE *tls_context)
 
231
{
 
232
    if (tls_context->peer_CN)
 
233
        myfree(tls_context->peer_CN);
 
234
    if (tls_context->issuer_CN)
 
235
        myfree(tls_context->issuer_CN);
 
236
    if (tls_context->peer_fingerprint)
 
237
        myfree(tls_context->peer_fingerprint);
 
238
    if (tls_context->protocol)
 
239
        myfree((char *) tls_context->protocol);
 
240
    if (tls_context->cipher_name)
 
241
        myfree((char *) tls_context->cipher_name);
 
242
    myfree((char *) tls_context);
 
243
}
 
244
 
 
245
#endif