Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 5023
Collapse All | Expand All

(-)postfix-1.1.11.20020613-orig/Makefile.in (-1 / +2 lines)
Lines 6-12 Link Here
6
	src/lmtp src/trivial-rewrite src/qmgr src/smtp src/bounce src/pipe \
6
	src/lmtp src/trivial-rewrite src/qmgr src/smtp src/bounce src/pipe \
7
	src/showq src/postalias src/postcat src/postconf src/postdrop \
7
	src/showq src/postalias src/postcat src/postconf src/postdrop \
8
	src/postkick src/postlock src/postlog src/postmap src/postqueue \
8
	src/postkick src/postlock src/postlog src/postmap src/postqueue \
9
	src/postsuper src/nqmgr src/qmqpd src/spawn src/flush src/virtual
9
	src/postsuper src/nqmgr src/qmqpd src/spawn src/flush src/virtual \
10
	src/tlsmgr
10
MANDIRS	= proto man html
11
MANDIRS	= proto man html
11
12
12
default: update
13
default: update
(-)postfix-1.1.11.20020613-orig/conf/master.cf (+5 lines)
Lines 70-80 Link Here
70
# 		(yes)	(yes)	(yes)	(never)	(50)
70
# 		(yes)	(yes)	(yes)	(never)	(50)
71
# ==========================================================================
71
# ==========================================================================
72
smtp	  inet	n	-	n	-	-	smtpd
72
smtp	  inet	n	-	n	-	-	smtpd
73
#smtps	  inet	n	-	n	-	-	smtpd
74
#  -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
75
#submission	inet	n	-	n	-	-	smtpd
76
#  -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes
73
#628	  inet	n	-	n	-	-	qmqpd
77
#628	  inet	n	-	n	-	-	qmqpd
74
pickup	  fifo	n	-	n	60	1	pickup
78
pickup	  fifo	n	-	n	60	1	pickup
75
cleanup	  unix	n	-	n	-	0	cleanup
79
cleanup	  unix	n	-	n	-	0	cleanup
76
qmgr	  fifo	n	-	n	300	1	qmgr
80
qmgr	  fifo	n	-	n	300	1	qmgr
77
#qmgr	  fifo	n	-	n	300	1	nqmgr
81
#qmgr	  fifo	n	-	n	300	1	nqmgr
82
#tlsmgr	  fifo	-	-	n	300	1	tlsmgr
78
rewrite	  unix	-	-	n	-	-	trivial-rewrite
83
rewrite	  unix	-	-	n	-	-	trivial-rewrite
79
bounce	  unix	-	-	n	-	0	bounce
84
bounce	  unix	-	-	n	-	0	bounce
80
defer	  unix	-	-	n	-	0	bounce
85
defer	  unix	-	-	n	-	0	bounce
(-)postfix-1.1.11.20020613-orig/conf/postfix-files (+3 lines)
Lines 69-74 Link Here
69
$daemon_directory/smtp:f:root:-:755
69
$daemon_directory/smtp:f:root:-:755
70
$daemon_directory/smtpd:f:root:-:755
70
$daemon_directory/smtpd:f:root:-:755
71
$daemon_directory/spawn:f:root:-:755
71
$daemon_directory/spawn:f:root:-:755
72
$daemon_directory/tlsmgr:f:root:-:755
72
$daemon_directory/trivial-rewrite:f:root:-:755
73
$daemon_directory/trivial-rewrite:f:root:-:755
73
$daemon_directory/virtual:f:root:-:755
74
$daemon_directory/virtual:f:root:-:755
74
$command_directory/postalias:f:root:-:755
75
$command_directory/postalias:f:root:-:755
Lines 139-144 Link Here
139
$manpage_directory/man8/smtp.8:f:root:-:644
140
$manpage_directory/man8/smtp.8:f:root:-:644
140
$manpage_directory/man8/smtpd.8:f:root:-:644
141
$manpage_directory/man8/smtpd.8:f:root:-:644
141
$manpage_directory/man8/spawn.8:f:root:-:644
142
$manpage_directory/man8/spawn.8:f:root:-:644
143
$manpage_directory/man8/tlsmgr.8:f:root:-:644
142
$manpage_directory/man8/trivial-rewrite.8:f:root:-:644
144
$manpage_directory/man8/trivial-rewrite.8:f:root:-:644
143
$manpage_directory/man8/virtual.8:f:root:-:644
145
$manpage_directory/man8/virtual.8:f:root:-:644
144
$sample_directory/sample-aliases.cf:f:root:-:644
146
$sample_directory/sample-aliases.cf:f:root:-:644
Lines 166-171 Link Here
166
$sample_directory/sample-rewrite.cf:f:root:-:644
168
$sample_directory/sample-rewrite.cf:f:root:-:644
167
$sample_directory/sample-smtp.cf:f:root:-:644
169
$sample_directory/sample-smtp.cf:f:root:-:644
168
$sample_directory/sample-smtpd.cf:f:root:-:644
170
$sample_directory/sample-smtpd.cf:f:root:-:644
171
$sample_directory/sample-tls.cf:f:root:-:644
169
$sample_directory/sample-transport.cf:f:root:-:644
172
$sample_directory/sample-transport.cf:f:root:-:644
170
$sample_directory/sample-virtual.cf:f:root:-:644
173
$sample_directory/sample-virtual.cf:f:root:-:644
171
$readme_directory/DB_README:f:root:-:644
174
$readme_directory/DB_README:f:root:-:644
(-)postfix-1.1.11.20020613-orig/conf/sample-auth.cf (+12 lines)
Lines 117-119 Link Here
117
#
117
#
118
#smtp_sasl_security_options = 
118
#smtp_sasl_security_options = 
119
smtp_sasl_security_options = noplaintext
119
smtp_sasl_security_options = noplaintext
120
121
# Sending AUTH data over an unencrypted channel poses a security risk. When
122
# smtpd_tls_enforce_tls is set, AUTH will only be announced and accepted,
123
# once the TLS layer has been activated via the STARTTLS protocol. If
124
# TLS layer encryption is optional, it may however still be useful to only
125
# offer AUTH, when TLS is active. To not break compatiblity with unpatched
126
# postfix versions, the default is to accept AUTH without encryption. In
127
# order to change this behaviour, set smtpd_tls_auth_only = yes.
128
# THIS OPTION ONLY WORKS WITH SSL/TLS SUPPORT COMPILED IN.
129
#
130
# smtpd_tls_auth_only = no
131
(-)postfix-1.1.11.20020613-orig/conf/sample-smtp.cf (+8 lines)
Lines 188-193 Link Here
188
#
188
#
189
smtp_helo_timeout = 300s
189
smtp_helo_timeout = 300s
190
190
191
# The smtp_starttls_timeout parameter limits the time in seconds to write and
192
# read operations during TLS start and stop handhake procedures.
193
#
194
# In case of problems the client does NOT try the next address on
195
# the mail exchanger list.
196
#
197
# smtp_starttls_timeout = 300s
198
191
# The smtp_mail_timeout parameter specifies the SMTP client timeout
199
# The smtp_mail_timeout parameter specifies the SMTP client timeout
192
# for sending the SMTP MAIL FROM command, and for receiving the server
200
# for sending the SMTP MAIL FROM command, and for receiving the server
193
# response.
201
# response.
(-)postfix-1.1.11.20020613-orig/conf/sample-smtpd.cf (+5 lines)
Lines 116-121 Link Here
116
# 
116
# 
117
strict_rfc821_envelopes = no
117
strict_rfc821_envelopes = no
118
118
119
# The smtpd_starttls_timeout parameter limits the time in seconds to write and
120
# read operations during TLS start and stop handhake procedures.
121
#
122
# smtpd_starttls_timeout = 300s
123
119
#
124
#
120
# TARPIT CONTROLS
125
# TARPIT CONTROLS
121
#
126
#
(-)postfix-1.1.11.20020613-orig/conf/sample-tls.cf (+497 lines)
Line 0 Link Here
1
# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF
2
# HERE JUST SERVES AS AN EXAMPLE.
3
#
4
# This file contains example settings of Postfix configuration
5
# parameters that control the behaviour of the TLS extensions.
6
#
7
# We strictly seperate between server side TLS (smtpd_) and client side
8
# TLS (smtp_), as for practical reasons we might choose differently.
9
10
# Section with SMTPD specific settings
11
12
# To use TLS we do need a certificate and a private key. Both must be in
13
# "pem" format, the private key must not be encrypted, that does mean:
14
# it must be accessable without password. Both parts (certificate and
15
# private key) may be in the same file.
16
#
17
# Both RSA and DSA are certificates are supported. Typically you will only
18
# have RSA certificates issued by a commercial CA, also the tools supplied
19
# with OpenSSL will by default issue RSA certificates.
20
# You can have both at the same time, in this case the cipher used decides,
21
# which certificate is presented. For Netscape and OpenSSL clients without
22
# special cipher choices, the RSA certificate is preferred.
23
#
24
# In order to check the certificates, the CA-certificate (in case of a
25
# certificate chain, all CA-certificates) must be available.
26
# You should add these certificates to the server certificate, the server
27
# certificate first, then the issuing CA(s).
28
#
29
# Example: the certificate for "server.dom.ain" was issued by "intermediate CA"
30
# which itself has a certificate of "root CA". Create the server.pem file by
31
# 'cat server_cert.pem intemediate_CA.pem root_CA.pem > server.pem'
32
#
33
# If you want to accept certificates issued by these CAs yourself, you can
34
# also add the CA-certificates to the smtpd_tls_CAfile, in which case it is
35
# not necessary to have them in the smtpd_tls_[d]cert_file.
36
#
37
# A certificate supplied here must be useable as SSL server certificate and
38
# hence pass the "openssl verify -purpose sslserver ..." test.
39
#
40
smtpd_tls_cert_file = /etc/postfix/server.pem
41
smtpd_tls_key_file = $smtpd_tls_cert_file
42
#
43
# Its DSA counterparts:
44
smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
45
smtpd_tls_dkey_file = $smtpd_tls_dcert_file
46
47
# The certificate was issued by a certification authority (CA), the CA-cert
48
# of which must be available, if not in the certificate file.
49
# This file may also contain the the CA certificates of other trusted CAs.
50
# You must use this file for the list of trusted CAs if you want to use
51
# chroot-mode. No default is supplied for this value as of now.
52
#
53
# smtpd_tls_CAfile = /etc/postfix/CAcert.pem
54
55
# To verify the peer certificate, we need to know the certificates of
56
# certification authorities. These certificates in "pem" format are
57
# collected in a directory. The same CAs are offered to clients for
58
# client verification. Don't forget to create the necessary "hash"
59
# links with $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs. A typical
60
# place for the CA-certs may also be $OPENSSL_HOME/certs, so there is
61
# no default and you explicitly have to set the value here!
62
#
63
# To use this option in chroot mode, this directory itself or a copy of it
64
# must be inside the chroot jail. Please note also, that the CAs in this
65
# directory are not listed to the client, so that e.g. Netscape might not
66
# offer certificates issued by them.
67
#
68
# I therefore discourage the use of this option.
69
#
70
smtpd_tls_CApath = /etc/postfix/certs
71
72
# To get additional information during the TLS setup and negotiations
73
# you can increase the loglevel from 0..4:
74
# 0: No output about the TLS subsystem
75
# 1: Printout startup and certificate information
76
# 2: 1 + Printout of levels during negotiation
77
# 3: 2 + Hex and ASCII dump of negotiation process
78
# 4: 3 + Hex and ASCII dump of complete transmission after STARTTLS
79
# Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
80
# discouraged.
81
#
82
# smtpd_tls_loglevel = 0
83
84
# To include information about the protocol and cipher used as well as the
85
# client and issuer CommonName into the "Received:" header, set the
86
# smtpd_tls_received_header variable to true. The default is no, as the
87
# information is not necessarily authentic. Only the final destination
88
# is reliable, since the headers might have been changed in between.
89
#
90
#smtpd_tls_received_header = yes
91
92
# By default TLS is disabled, so no difference to plain postfix is visible.
93
# Explicitely switch it on using "smtpd_use_tls". (Note: when invoked
94
# via "sendmail -bs", STARTTLS is never offered due to insufficient
95
# privileges to access the private key. This is intended behaviour.)
96
#
97
smtpd_use_tls = yes
98
99
# You can ENFORCE the use of TLS, so that no commands (except QUIT of course)
100
# are allowed without TLS. According to RFC2487 this MUST NOT be applied
101
# in case of a publicly-referenced SMTP server. So this option is off
102
# by default and should only seldom be used. Using this option implies
103
# smtpd_use_tls = yes. (Note: when invoked via "sendmail -bs", STARTTLS
104
# is never offered due to insufficient privileges to access the private key.
105
# This is intended behaviour.)
106
#
107
# smtpd_enforce_tls = no
108
109
# Besides RFC2487 some clients, namely Outlook [Express] prefer to run the
110
# non-standard "wrapper" mode, not the STARTTLS enhancement to SMTP.
111
# This is true for OE (Win32 < 5.0 and Win32 >=5.0 when run on a port!=25
112
# and OE (5.01 Mac on all ports).
113
# It is strictly discouraged to use this mode from main.cf. If you want to
114
# support this service, enable a special port in master.cf. Port 465 (smtps)
115
# was once chosen for this feature.
116
#
117
# smtpd_tls_wrappermode = no
118
119
# To receive a client certificate, the server must explicitly ask for one.
120
# Hence netscape will either complain if no certificate is available (for
121
# the list of CAs in /etc/postfix/certs) or will offer you client certificates
122
# to choose from. This might be annoying, so this option is "off" by default.
123
# You will however need the certificate if you want to to e.g. certificate
124
# based relaying.
125
#
126
# smtpd_tls_ask_ccert = no
127
128
# You may also decide to REQUIRE a client certificate to allow TLS connections.
129
# I don't think it will be necessary often, it is however included here for
130
# completeness. This option implies smtpd_tls_ask_ccert = yes
131
#
132
# Please be aware, that this will inhibit TLS connections without a proper
133
# certificate and only makes sense, when normal submission is disabled and
134
# TLS is enforced (smtpd_enforce_tls). Otherwise clients may bypass by simply
135
# not using STARTTLS at all. When TLS is not enforced, the connection will be
136
# handled, as if only smtpd_tls_ask_ccert = yes would be set and an information
137
# is logged.
138
#
139
# smtpd_tls_req_ccert = no
140
141
# The verification depth for client certificates. A depth of 1 is sufficient,
142
# if the certificate ist directly issued by a CA listed in the CA locations.
143
# The default value (5) should also suffice for longer chains (root CA issues
144
# special CA which then issues the actual certificate...)
145
#
146
# smtpd_tls_ccert_verifydepth = 5
147
148
# Sending AUTH data over an unencrypted channel poses a security risk. When
149
# smtpd_tls_enforce_tls is set, AUTH will only be announced and accepted,
150
# once the TLS layer has been activated via the STARTTLS protocol. If
151
# TLS layer encryption is optional, it may however still be useful to only
152
# offer AUTH, when TLS is active. To not break compatiblity with unpatched
153
# postfix versions, the default is to accept AUTH without encryption. In
154
# order to change this behaviour, set smtpd_tls_auth_only = yes.
155
#
156
# smtpd_tls_auth_only = no
157
158
# The server and client negotiate a session, which takes some computer time
159
# and network bandwidth. The session is cached only in the smtpd process
160
# actually using this session and is lost when the process dies.
161
# To share the session information between the smtpd processes, a disc based
162
# session cache can be used based on the SDBM databases (routines included
163
# in Postfix/TLS). Since concurrent writing must be supported, only SDBM
164
# can be used.
165
#
166
smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache
167
168
# The cached sessions time out after a certain amount of time. For Postfix/TLS
169
# I do not use the OpenSSL default of 300sec, but a longer time of 3600sec
170
# (=1 hour). RFC2246 recommends a maximum of 24 hours.
171
#
172
# smtpd_tls_session_cache_timeout = 3600s
173
174
# Two additional options has been added for relay control to the UCE rules:
175
#   permit_tls_clientcerts	(a)
176
# and
177
#   permit_tls_all_clientcerts. (b)
178
#
179
# If one of these options is added to
180
#   smtpd_recipient_restrictions,
181
# postfix will relay if 
182
# (a) a valid (it passed the verification) client certificate is presented
183
#     and its fingerprint is listed in the list of client certs
184
#     (relay_clientcerts),
185
# (b) any valid (it passed the verification) client certificate is presented.
186
#
187
# Option (b) must only be used, if a special CA issues the certificates and
188
# only this CA is listed as trusted CA. If other CAs are trusted, any owner
189
# of a valid (SSL client)-certificate can relay. Option (b) can be practical
190
# for a specically created email relay. It is however recommended to stay with
191
# option (a) and list all certificates, as (b) does not permit any control
192
# when a certificate must no longer be used (e.g. an employee leaving).
193
#
194
# smtpd_recipient_restrictions = ... permit_tls_clientcerts ...
195
196
# The list of client certificates for which relaying will be allowed.
197
# Unfortunately the routines for lists in postfix use whitespaces as
198
# seperators and choke on special chars. So using the certificate
199
# X509ONELINES is quite impractical. We will use the fingerprints at
200
# this point, as they are difficult to fake but easy to use for lookup.
201
# As postmap (when using e.g. db) insists of having a pair of key and value,
202
# but we only need the key, the value can be chosen freely, e.g. the name
203
# of the user or host:
204
# D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
205
#
206
# relay_clientcerts = hash:/etc/postfix/relay_clientcerts
207
208
# To influence the cipher selection scheme, you can give cipherlist-string.
209
# A detailed description would go to far here, please refer to the openssl
210
# documentation.
211
# If you don't know what to do with it, simply don't touch it and leave the
212
# (openssl-)compiled in default!
213
#
214
# DO NOT USE " to enclose the string, just the string!!!
215
#
216
# smtpd_tls_cipherlist = DEFAULT
217
218
# If you want to take advantage of ciphers with EDH, DH parameters are needed.
219
# There are built in DH parameters for both 1025bit and 512bit available. It
220
# is however better to have "own" parameters, since otherwise it would "pay"
221
# for a possible attacker to start a brute force attack against these
222
# parameters commonly used by everybody. For this reason, the parameters
223
# chosen are already different from those distributed with other TLS packages.
224
#
225
# To generate your own set of parameters, use
226
# openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024
227
# openssl gendh -out /etc/postfix/dh_512.pem -2 -rand /var/run/egd-pool 512
228
# (your source for "entropy" might vary; on Linux there is /dev/random, on
229
# other system, you might consider the "Entropy Gathering Daemon EGD", 
230
# available at http://www.lothar.com/tech/crypto/.
231
#
232
smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
233
smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
234
235
# The smtpd_starttls_timeout parameter limits the time in seconds to write and
236
# read operations during TLS start and stop handhake procedures.
237
#
238
# smtpd_starttls_timeout = 300s
239
240
# Section with SMTP specific settings
241
242
# During the startup negotiation we might present a certificate to the server.
243
# Netscape is rather clever here and lets the user select between only those
244
# certs that will match the CAs accepted from the server. As I simply use
245
# the integrated "SSL_connect()" from the OpenSSL package, this is not
246
# possible by now and we have to chose just one cert.
247
# So for now the default is to use _no_ cert and key unless explictly
248
# set here. It is possible to use the same key/cert pair as for the server.
249
# If a cert is to be presented, it must be in "pem" format, the private key
250
# must not be encrypted, that does mean: it must be accessable without
251
# password. Both parts (certificate and private key) may be in the
252
# same file.
253
#
254
# In order to check the certificates, the CA-certificate (in case of a
255
# certificate chain, all CA-certificates) must be available.
256
# You should add these certificates to the server certificate, the server
257
# certificate first, then the issuing CA(s).
258
#
259
# Example: the certificate for "client.dom.ain" was issued by "intermediate CA"
260
# which itself has a certificate of "root CA". Create the client.pem file by
261
# 'cat client_cert.pem intemediate_CA.pem root_CA.pem > client.pem'
262
#
263
# If you want to accept certificates issued by these CAs yourself, you can
264
# also add the CA-certificates to the smtp_tls_CAfile, in which case it is
265
# not necessary to have them in the smtp_tls_[d]cert_file.
266
#
267
# A certificate supplied here must be useable as SSL client certificate and
268
# hence pass the "openssl verify -purpose sslclient ..." test.
269
#
270
smtp_tls_cert_file = /etc/postfix/client.pem
271
smtp_tls_key_file = $smtp_tls_cert_file
272
273
# The certificate was issued by a certification authority (CA), the CA-cert
274
# of which must be available, if not in the certificate file.
275
# This file may also contain the the CA certificates of other trusted CAs.
276
# You must use this file for the list of trusted CAs if you want to use
277
# chroot-mode. No default is supplied for this value as of now.
278
#
279
smtp_tls_CAfile = /etc/postfix/CAcert.pem
280
281
# To verify the peer certificate, we need to know the certificates of
282
# certification authorities. These certificates in "pem" format are
283
# collected in a directory. Don't forget to create the necessary "hash"
284
# links with $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs. A typical
285
# place for the CA-certs may also be $OPENSSL_HOME/certs, so there is
286
# no default and you explicitly have to set the value here!
287
#
288
# To use this option in chroot mode, this directory itself or a copy of it
289
# must be inside the chroot jail.
290
#
291
smtp_tls_CApath = /etc/postfix/certs
292
293
# To get additional information during the TLS setup and negotiations
294
# you can increase the loglevel from 0..4:
295
# 0: No output about the TLS subsystem
296
# 1: Printout startup and certificate information
297
# 2: 1 + Printout of levels during negotiation
298
# 3: 2 + Hex and ASCII dump of negotiation process
299
# 4: 3 + Hex and ASCII dump of complete transmission after STARTTLS
300
# Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
301
# discouraged.
302
#
303
smtp_tls_loglevel = 0
304
305
# The server and client negotiate a session, which takes some computer time
306
# and network bandwidth. The session is cached only in the smtpd process
307
# actually using this session and is lost when the process dies.
308
# To share the session information between the smtp processes, a disc based
309
# session cache can be used based on the SDBM databases (routines included
310
# in Postfix/TLS). Since concurrent writing must be supported, only SDBM
311
# can be used.
312
#
313
smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache
314
315
# The cached sessions time out after a certain amount of time. For Postfix/TLS
316
# I do not use the OpenSSL default of 300sec, but a longer time of 3600sec
317
# (=1 hour). RFC2246 recommends a maximum of 24 hours.
318
#
319
# smtp_tls_session_cache_timeout = 3600s
320
321
# By default TLS is disabled, so no difference to plain postfix is visible.
322
# If you enable TLS it will be used when offered by the server.
323
# WARNING: I didn't have access to other software (except those explicitely
324
# listed) to test the interaction. On corresponding mailing list
325
# there was a discussion going on about MS exchange servers offering
326
# STARTTLS even if it is not configured, so it might be wise to not
327
# use this option on your central mail hub, as you don't know in advance
328
# whether you are going to hit such host. Use the recipient/site specific
329
# options instead.
330
# HINT: I have it switched on on my mailservers and did experience one
331
# single failure since client side TLS is implemented. (There was one
332
# misconfired MS Exchange server; I contacted ths admin.) Hence, I am happy
333
# with it running all the time, but I am interested in testing anyway.
334
# You have been warned, however :-)
335
#
336
# In case of failure, a "4xx" code is issued and the mail stays in the queue.
337
#
338
# Explicitely switch it on here, if you want it.
339
#
340
smtp_use_tls = yes
341
342
# You can ENFORCE the use of TLS, so that only connections with TLS will
343
# be accepted. Additionally, the hostname of the receiving host is matched
344
# against the CommonName in the certificate. Also, the certificate must
345
# be verified "Ok", so that a CA trusted by the client must have issued
346
# the certificate. If the certificate doesn't verify or the hostname doesn't
347
# match, a "4xx" will be issued and the mail stays in the queue.
348
# The hostname used in the check is beyond question, as it must be the
349
# principle hostname (no CNAME allowed here).
350
# The behaviour may be changed with the smtp_tls_enforce_peername option
351
#
352
# This option is useful only if you are definitely sure that you will only
353
# connect to servers supporting RFC2487 _and_ with valid certificates.
354
# I use it for my clients which will only send email to one mailhub, which
355
# does offer the necessary STARTTLS support.
356
#
357
# smtp_enforce_tls = no
358
359
# As of RFC2487 the requirements for hostname checking for MTA clients are
360
# not set. When in smtp_enforce_tls mode, the option smtp_tls_enforce_peername
361
# can be set to "no" to disable strict peername checking. In this case, the
362
# mail delivery will be continued, if a TLS connection was established
363
# _and_ the peer certificate passed verification _but_ regardless of the
364
# CommonName listed in the certificate. This option only applies to the
365
# default setting smtp_enforce_tls_mode, special settings in the
366
# smtp_tls_per_site table override smtp_tls_enforce_peername.
367
#
368
# This can make sense in closed environment where special CAs are created.
369
# If not used carefully, this option opens the danger of a "man-in-the-middle"
370
# attack (the CommonName of this attacker is logged).
371
#
372
# smtp_tls_enforce_peername = yes
373
374
# As generally trying TLS can be a bad idea (some hosts offer STARTTLS but
375
# the negotiation will fail leading to unexplainable failures, it may be
376
# a good idea to decide based on the recipient or the mailhub to which you are
377
# connecting.
378
#
379
# Deciding per recipient may be difficult, since a singe email can have
380
# several recipients. We use the "nexthop" mechanism inside postfix.
381
# When an email is to be delivered, the "nexthop" is obtained. If it matches
382
# an entry in the smtp_tls_per_site list, appropriate action is taken.
383
# Since entries in the transport table or the use of a relay_host override
384
# the nexthop setting, in these cases the relay_host etc must be listed
385
# in the table. In any case, the hostname of the peer to be contacted is
386
# looked up (that is: the MX or the name of the host, if no MX is given).
387
#
388
# Special hint for enforcement mode:
389
# Since there is no secure mechanism for DNS lookups available, the
390
# recommended setup is: put the sensible domains with their mailhost
391
# into the transport table (since you can asure security of this table
392
# unlike DNS), then set MUST mode for this mailhost.
393
#
394
# Format of the table:
395
# The keys entries are on the left hand side, no wildcards allowed. On the
396
# right hand side the keywords NONE (don't use TLS at all), MAY (try to use
397
# STARTTLS if offered, no problem if not), MUST (enforce usage of STARTTLS,
398
# check server certificate CommonName against server FQDN), MUST_NOPEERMATCH
399
# (enforce usage of STARTTLS and verify certificate, but ignore differences
400
# between CommonName and server FQDN).
401
# dom.ain		NONE
402
# host.dom.ain		MAY
403
# important.host	MUST
404
# some.host.dom.ain	MUST_NOPEERMATCH
405
#
406
# If an entry is not matched, the default policy is applied; if the default
407
# policy is "enforce", NONE explicitely switches it off, otherwise the
408
# "enforce" mode is used even for MAY entries.
409
#
410
smtp_tls_per_site = hash:/etc/postfix/tls_per_site
411
412
# The verification depth for server certificates. A depth of 1 is sufficient,
413
# if the certificate ist directly issued by a CA listed in the CA locations.
414
# The default value (5) should also suffice for longer chains (root CA issues
415
# special CA which then issues the actual certificate...)
416
#
417
# smtp_tls_scert_verifydepth = 5
418
419
# As we decide on a "per site" basis, wether to use TLS or not, it would be
420
# good to have a list of sites, that offered "STARTTLS'. We can collect it
421
# ourselves with this option.
422
#
423
# If activated and TLS is not already enabled for this host, a line is added
424
# to the logfile:
425
# postfix/smtp[pid]: Host offered STARTTLS: [name.of.host]
426
#
427
smtp_tls_note_starttls_offer = yes
428
429
# To influence the cipher selection scheme, you can give cipherlist-string.
430
# A detailed description would go to far here, please refer to the openssl
431
# documentation.
432
# If you don't know what to do with it, simply don't touch it and leave the
433
# (openssl-)compiled in default!
434
#
435
# DO NOT USE " to enclose the string, just the string!!!
436
#
437
# smtp_tls_cipherlist = DEFAULT
438
439
# The smtp_starttls_timeout parameter limits the time in seconds to write and
440
# read operations during TLS start and stop handhake procedures.
441
#
442
# In case of problems the client does NOT try the next address on
443
# the mail exchanger list.
444
#
445
# smtp_starttls_timeout = 300s
446
447
# In order to seed the PRNG Pseude Random Number Generator, random data is
448
# needed. The PRNG pool is maintained by the "tlsmgr" daemon and is used
449
# (read) by the smtp[d] processes after adding some more entropy by stirring
450
# in time and process id.
451
# The file, which is from time to time rewritten by the tlsmgr, is created
452
# if not existant. A default value is given; the default should probably
453
# be on the /var partition but _not_ inside chroot jail.
454
#
455
# tls_random_exchange_name = /etc/postfix/prng_exch
456
457
# To feed the PRNG pool, entropy is being read from an external source,
458
# both at startup and during run.
459
# Specify a good entropy source here, like EGD or /dev/urandom; make sure
460
# to only use non-blocking sources.
461
# In both cases, 32 bytes are read at each re-seeding event (which is an
462
# amount of 256bits and hence good enough for 128bit symmetric keys).
463
# You must specify the type of source: "dev:" for a device special file
464
# or "egd:" for a source with EGD compatible socket interface. A maximum
465
# 255 bytes is read from these sources in each step.
466
# If you specify a normal file, a larger amount of data can be read.
467
#
468
# The entropy source is queried again after a certain amount of time. The
469
# time is calculated using the PRNG, it is between 0 and the time specified,
470
# default is a maximum of 1 hour.
471
#
472
# tls_random_source = dev:/dev/urandom
473
tls_random_source = egd:/var/run/egd-pool
474
# tls_random_bytes = 32
475
# tls_random_reseed_period = 3600s
476
477
# The PRNG pool inside tlsmgr is used to re-generate the 1024 byte file
478
# being read by smtp[d]. The time, after which the exchange file is
479
# rewritten is calculated using the PRNG, it is between 0 and the time
480
# specified, default is a maximum of 60 seconds.
481
#
482
# tls_random_upd_period = 60s
483
484
# If you have a entropy source available, that is not easily drained (like
485
# /dev/urandom), the daemons can also load additional entropy on startup from
486
# the source specified. By default an amount of 32 bytes is read, the
487
# equivalent to 256 bits. This is more than enough to generate a 128bit
488
# (or 168bit) session key, but we may have to generate more than one.
489
# Usage of this option may drain EGD (consider the case of 50 smtp starting
490
# up with a full queue and "postfix start", which will request 1600bytes
491
# of entropy). This is however not fatal, as long as "entropy" data could
492
# be read from the exchange file.
493
#
494
# tls_daemon_random_source = dev:/dev/urandom
495
tls_daemon_random_source = egd:/var/run/egd-pool
496
# tls_daemon_random_bytes = 32
497
(-)postfix-1.1.11.20020613-orig/makedefs (+35 lines)
Lines 52-57 Link Here
52
SYSTEM=`(uname -s) 2>/dev/null`
52
SYSTEM=`(uname -s) 2>/dev/null`
53
RELEASE=`(uname -r) 2>/dev/null`
53
RELEASE=`(uname -r) 2>/dev/null`
54
VERSION=`(uname -v) 2>/dev/null`
54
VERSION=`(uname -v) 2>/dev/null`
55
if test -f /usr/include/netinet6/in6.h; then
56
	grep __KAME__ /usr/include/netinet6/in6.h 2>&1 >/dev/null
57
	if [ $?  = 1 ]; then
58
		INET6=
59
	else
60
		if [ -f /usr/local/v6/lib/libinet6.a ]; then
61
			INET6=kame
62
		else
63
			INET6=kame-merged
64
		fi
65
	fi
66
fi
67
if [ -z "$INET6" -a -f /usr/include/netinet/ip6.h -a -f /usr/include/linux/icmpv6.h ]; then
68
	INET6=linux
69
fi
55
70
56
case "$VERSION" in
71
case "$VERSION" in
57
 dcosx*) SYSTEM=$VERSION;;
72
 dcosx*) SYSTEM=$VERSION;;
Lines 295-300 Link Here
295
esac
310
esac
296
311
297
: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
312
: ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
313
314
case "$INET6" in
315
kame)
316
	CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
317
	if test -f /usr/local/v6/lib/libinet6.a; then
318
		SYSLIBS="$SYSLIBS -L/usr/local/v6/lib -linet6"
319
	fi
320
	;;
321
kame-merged)
322
	CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
323
	;;
324
linux)
325
	CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family"
326
	if test -f /usr/include/libinet6/netinet/ip6.h -a \
327
		-f /usr/lib/libinet6.a; then 
328
		CCARGS="$CCARGS -I/usr/include/libinet6 -DUSAGI_LIBINET6"
329
		SYSLIBS="$SYSLIBS -linet6"
330
	fi
331
	;;
332
esac
298
333
299
export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
334
export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
300
335
(-)postfix-1.1.11.20020613-orig/man/man8/tlsmgr.8 (+130 lines)
Line 0 Link Here
1
.TH TLSMGR 8 
2
.ad
3
.fi
4
.SH NAME
5
tlsmgr
6
\-
7
Postfix TLS session cache and PRNG handling manager
8
.SH SYNOPSIS
9
.na
10
.nf
11
\fBtlsmgr\fR [generic Postfix daemon options]
12
.SH DESCRIPTION
13
.ad
14
.fi
15
The tlsmgr process does housekeeping on the session cache database
16
files. It runs through the databases and removes expired entries
17
and entries written by older (incompatible) versions.
18
19
The tlsmgr is responsible for the PRNG handling. The used internal
20
OpenSSL PRNG has a pool size of 8192 bits (= 1024 bytes). The pool
21
is initially seeded at startup from an external source (EGD or
22
/dev/urandom) and additional seed is obtained later during program
23
run at a configurable period. The exact time of seed query is
24
using random information and is equally distributed in the range of
25
[0-\fBtls_random_reseed_period\fR] with a \fBtls_random_reseed_period\fR
26
having a default of 1 hour.
27
28
Tlsmgr can be run chrooted and with dropped privileges, as it will
29
connect to the entropy source at startup.
30
31
The PRNG is additionally seeded internally by the data found in the
32
session cache and timevalues.
33
34
Tlsmgr reads the old value of the exchange file at startup to keep
35
entropy already collected during previous runs.
36
37
From the PRNG random pool a cryptographically strong 1024 byte random
38
sequence is written into the PRNG exchange file. The file is updated
39
periodically with the time changing randomly from
40
[0-\fBtls_random_prng_update_period\fR].
41
.SH STANDARDS
42
.na
43
.nf
44
.SH SECURITY
45
.na
46
.nf
47
.ad
48
.fi
49
Tlsmgr is not security-sensitive. It only deals with external data
50
to be fed into the PRNG, the contents is never trusted. The session
51
cache housekeeping will only remove entries if expired and will never
52
touch the contents of the cached data.
53
.SH DIAGNOSTICS
54
.ad
55
.fi
56
Problems and transactions are logged to the syslog daemon.
57
.SH BUGS
58
.ad
59
.fi
60
There is no automatic means to limit the number of entries in the
61
session caches and/or the size of the session cache files.
62
.SH CONFIGURATION PARAMETERS
63
.na
64
.nf
65
.ad
66
.fi
67
The following \fBmain.cf\fR parameters are especially relevant to
68
this program. See the Postfix \fBmain.cf\fR file for syntax details
69
and for default values. Use the \fBpostfix reload\fR command after
70
a configuration change.
71
.SH Session Cache
72
.ad
73
.fi
74
.IP \fBsmtpd_tls_session_cache_database\fR
75
Name of the SDBM file (type sdbm:) containing the SMTP server session
76
cache. If the file does not exist, it is created.
77
.IP \fBsmtpd_tls_session_cache_timeout\fR
78
Expiry time of SMTP server session cache entries in seconds. Entries
79
older than this are removed from the session cache. A cleanup-run is
80
performed periodically every \fBsmtpd_tls_session_cache_timeout\fR
81
seconds. Default is 3600 (= 1 hour).
82
.IP \fBsmtp_tls_session_cache_database\fR
83
Name of the SDBM file (type sdbm:) containing the SMTP client session
84
cache. If the file does not exist, it is created.
85
.IP \fBsmtp_tls_session_cache_timeout\fR
86
Expiry time of SMTP client session cache entries in seconds. Entries
87
older than this are removed from the session cache. A cleanup-run is
88
performed periodically every \fBsmtp_tls_session_cache_timeout\fR
89
seconds. Default is 3600 (= 1 hour).
90
.SH Pseudo Random Number Generator
91
.ad
92
.fi
93
.IP \fBtls_random_source\fR
94
Name of the EGD socket or device or regular file to obtain entropy
95
from. The type of entropy source must be specified by preceding the
96
name with the appropriate type: egd:/path/to/egd_socket,
97
dev:/path/to/devicefile, or /path/to/regular/file.
98
tlsmgr opens \fBtls_random_source\fR and tries to read
99
\fBtls_random_bytes\fR from it.
100
.IP \fBtls_random_bytes\fR
101
Number of bytes to be read from \fBtls_random_source\fR.
102
Default value is 32 bytes. If using EGD, a maximum of 255 bytes is read.
103
.IP \fBtls_random_exchange_name\fR
104
Name of the file written by tlsmgr and read by smtp and smtpd at
105
startup. The length is 1024 bytes. Default value is
106
/etc/postfix/prng_exch.
107
.IP \fBtls_random_reseed_period\fR
108
Time in seconds until the next reseed from external sources is due.
109
This is the maximum value. The actual point in time is calculated
110
with a random factor equally distributed between 0 and this maximum
111
value. Default is 3600 (= 60 minutes).
112
.IP \fBtls_random_prng_update_period\fR
113
Time in seconds until the PRNG exchange file is updated with new
114
pseude random values. This is the maximum value. The actual point
115
in time is calculated with a random factor equally distributed
116
between 0 and this maximum value. Default is 60 (= 1 minute).
117
.SH SEE ALSO
118
.na
119
.nf
120
smtp(8) SMTP client
121
smtpd(8) SMTP server
122
.SH LICENSE
123
.na
124
.nf
125
.ad
126
.fi
127
The Secure Mailer license must be distributed with this software.
128
.SH AUTHOR(S)
129
.na
130
.nf
(-)postfix-1.1.11.20020613-orig/src/dns/dns_lookup.c (+16 lines)
Lines 132-137 Link Here
132
} DNS_REPLY;
132
} DNS_REPLY;
133
133
134
#define INET_ADDR_LEN	4		/* XXX */
134
#define INET_ADDR_LEN	4		/* XXX */
135
#ifdef INET6
136
#define INET6_ADDR_LEN	16
137
#endif
135
138
136
/* dns_query - query name server and pre-parse the reply */
139
/* dns_query - query name server and pre-parse the reply */
137
140
Lines 337-342 Link Here
337
	memcpy(temp, pos, fixed->length);
340
	memcpy(temp, pos, fixed->length);
338
	data_len = fixed->length;
341
	data_len = fixed->length;
339
	break;
342
	break;
343
#ifdef INET6
344
    case T_AAAA:
345
	if (fixed->length != INET6_ADDR_LEN) {
346
	    msg_warn("extract_answer: bad IPv6 address length: %d", fixed->length);
347
	    return (0);
348
	}
349
	if (fixed->length > sizeof(temp))
350
	    msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
351
		      fixed->length);
352
	memcpy(temp, pos, fixed->length);
353
	data_len = fixed->length;
354
	break;
355
#endif
340
    case T_TXT:
356
    case T_TXT:
341
	data_len = MIN2(pos[0] + 1, MIN2(fixed->length + 1, sizeof(temp)));
357
	data_len = MIN2(pos[0] + 1, MIN2(fixed->length + 1, sizeof(temp)));
342
	for (src = pos + 1, dst = (unsigned char *) (temp);
358
	for (src = pos + 1, dst = (unsigned char *) (temp);
(-)postfix-1.1.11.20020613-orig/src/global/Makefile.in (-3 / +16 lines)
Lines 20-26 Link Here
20
	tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
20
	tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
21
	flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
21
	flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
22
	verp_sender.c match_parent_style.c mime_state.c header_token.c \
22
	verp_sender.c match_parent_style.c mime_state.c header_token.c \
23
	strip_addr.c
23
	strip_addr.c pfixtls.c wildcard_inet_addr.c
24
OBJS	= been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
24
OBJS	= been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
25
	debug_peer.o debug_process.o defer.o deliver_completed.o \
25
	debug_peer.o debug_process.o defer.o deliver_completed.o \
26
	deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
26
	deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
Lines 42-48 Link Here
42
	tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
42
	tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
43
	flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
43
	flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
44
	verp_sender.o match_parent_style.o mime_state.o header_token.o \
44
	verp_sender.o match_parent_style.o mime_state.o header_token.o \
45
	strip_addr.o
45
	strip_addr.o pfixtls.o wildcard_inet_addr.o
46
HDRS	= been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
46
HDRS	= been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
47
	config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
47
	config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
48
	deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
48
	deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
Lines 60-66 Link Here
60
	sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
60
	sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
61
	mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
61
	mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
62
	match_parent_style.h quote_flags.h mime_state.h header_token.h \
62
	match_parent_style.h quote_flags.h mime_state.h header_token.h \
63
	lex_822.h strip_addr.h
63
	lex_822.h strip_addr.h pfixtls.h wildcard_inet_addr.h
64
TESTSRC	= rec2stream.c stream2rec.c recdump.c
64
TESTSRC	= rec2stream.c stream2rec.c recdump.c
65
WARN	= -W -Wformat -Wimplicit -Wmissing-prototypes \
65
WARN	= -W -Wformat -Wimplicit -Wmissing-prototypes \
66
	-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
66
	-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
Lines 1160-1162 Link Here
1160
xtext.o: ../../include/vbuf.h
1160
xtext.o: ../../include/vbuf.h
1161
xtext.o: ../../include/vstring.h
1161
xtext.o: ../../include/vstring.h
1162
xtext.o: xtext.h
1162
xtext.o: xtext.h
1163
pfixtls.o: pfixtls.c
1164
pfixtls.o: ../../include/sys_defs.h
1165
pfixtls.o: ../../include/iostuff.h
1166
pfixtls.o: ../../include/mymalloc.h
1167
pfixtls.o: ../../include/vstring.h
1168
pfixtls.o: ../../include/vstream.h
1169
pfixtls.o: ../../include/dict.h
1170
pfixtls.o: ../../include/myflock.h
1171
pfixtls.o: ../../include/stringops.h
1172
pfixtls.o: ../../include/msg.h
1173
pfixtls.o: ../../include/connect.h
1174
pfixtls.o: mail_params.h
1175
pfixtls.o: pfixtls.h
(-)postfix-1.1.11.20020613-orig/src/global/mail_params.c (+50 lines)
Lines 223-228 Link Here
223
int     var_in_flow_delay;
223
int     var_in_flow_delay;
224
char   *var_par_dom_match;
224
char   *var_par_dom_match;
225
char   *var_config_dirs;
225
char   *var_config_dirs;
226
char   *var_tls_rand_exch_name;
227
char   *var_smtpd_tls_cert_file;
228
char   *var_smtpd_tls_key_file;
229
char   *var_smtpd_tls_dcert_file;
230
char   *var_smtpd_tls_dkey_file;
231
char   *var_smtpd_tls_CAfile;
232
char   *var_smtpd_tls_CApath;
233
char   *var_smtpd_tls_cipherlist;
234
char   *var_smtpd_tls_dh512_param_file;
235
char   *var_smtpd_tls_dh1024_param_file;
236
int     var_smtpd_tls_loglevel;
237
char   *var_smtpd_tls_scache_db;
238
int     var_smtpd_tls_scache_timeout;
239
char   *var_smtp_tls_cert_file;
240
char   *var_smtp_tls_key_file;
241
char   *var_smtp_tls_dcert_file;
242
char   *var_smtp_tls_dkey_file;
243
char   *var_smtp_tls_CAfile;
244
char   *var_smtp_tls_CApath;
245
char   *var_smtp_tls_cipherlist;
246
int     var_smtp_tls_loglevel;
247
char   *var_smtp_tls_scache_db;
248
int     var_smtp_tls_scache_timeout;
249
char   *var_tls_daemon_rand_source;
250
int     var_tls_daemon_rand_bytes;
226
251
227
char   *var_import_environ;
252
char   *var_import_environ;
228
char   *var_export_environ;
253
char   *var_export_environ;
Lines 467-472 Link Here
467
	VAR_SHOWQ_SERVICE, DEF_SHOWQ_SERVICE, &var_showq_service, 1, 0,
492
	VAR_SHOWQ_SERVICE, DEF_SHOWQ_SERVICE, &var_showq_service, 1, 0,
468
	VAR_ERROR_SERVICE, DEF_ERROR_SERVICE, &var_error_service, 1, 0,
493
	VAR_ERROR_SERVICE, DEF_ERROR_SERVICE, &var_error_service, 1, 0,
469
	VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0,
494
	VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0,
495
	VAR_TLS_RAND_EXCH_NAME, DEF_TLS_RAND_EXCH_NAME, &var_tls_rand_exch_name, 0, 0,
496
	VAR_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CERT_FILE, &var_smtpd_tls_cert_file, 0, 0,
497
	VAR_SMTPD_TLS_KEY_FILE, DEF_SMTPD_TLS_KEY_FILE, &var_smtpd_tls_key_file, 0, 0,
498
	VAR_SMTPD_TLS_DCERT_FILE, DEF_SMTPD_TLS_DCERT_FILE, &var_smtpd_tls_dcert_file, 0, 0,
499
	VAR_SMTPD_TLS_DKEY_FILE, DEF_SMTPD_TLS_DKEY_FILE, &var_smtpd_tls_dkey_file, 0, 0,
500
	VAR_SMTPD_TLS_CA_FILE, DEF_SMTPD_TLS_CA_FILE, &var_smtpd_tls_CAfile, 0, 0,
501
	VAR_SMTPD_TLS_CA_PATH, DEF_SMTPD_TLS_CA_PATH, &var_smtpd_tls_CApath, 0, 0,
502
	VAR_SMTPD_TLS_CLIST, DEF_SMTPD_TLS_CLIST, &var_smtpd_tls_cipherlist, 0, 0,
503
	VAR_SMTPD_TLS_512_FILE, DEF_SMTPD_TLS_512_FILE, &var_smtpd_tls_dh512_param_file, 0, 0,
504
	VAR_SMTPD_TLS_1024_FILE, DEF_SMTPD_TLS_1024_FILE, &var_smtpd_tls_dh1024_param_file, 0, 0,
505
	VAR_SMTPD_TLS_SCACHE_DB, DEF_SMTPD_TLS_SCACHE_DB, &var_smtpd_tls_scache_db, 0, 0,
506
	VAR_SMTP_TLS_CERT_FILE, DEF_SMTP_TLS_CERT_FILE, &var_smtp_tls_cert_file, 0, 0,
507
	VAR_SMTP_TLS_KEY_FILE, DEF_SMTP_TLS_KEY_FILE, &var_smtp_tls_key_file, 0, 0,
508
	VAR_SMTP_TLS_DCERT_FILE, DEF_SMTP_TLS_DCERT_FILE, &var_smtp_tls_dcert_file, 0, 0,
509
	VAR_SMTP_TLS_DKEY_FILE, DEF_SMTP_TLS_DKEY_FILE, &var_smtp_tls_dkey_file, 0, 0,
510
	VAR_SMTP_TLS_CA_FILE, DEF_SMTP_TLS_CA_FILE, &var_smtp_tls_CAfile, 0, 0,
511
	VAR_SMTP_TLS_CA_PATH, DEF_SMTP_TLS_CA_PATH, &var_smtp_tls_CApath, 0, 0,
512
	VAR_SMTP_TLS_CLIST, DEF_SMTP_TLS_CLIST, &var_smtp_tls_cipherlist, 0, 0,
513
	VAR_SMTP_TLS_SCACHE_DB, DEF_SMTP_TLS_SCACHE_DB, &var_smtp_tls_scache_db, 0, 0,
514
	VAR_TLS_DAEMON_RAND_SOURCE, DEF_TLS_DAEMON_RAND_SOURCE, &var_tls_daemon_rand_source, 0, 0,
470
	0,
515
	0,
471
    };
516
    };
472
    static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
517
    static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
Lines 489-494 Link Here
489
	VAR_TOKEN_LIMIT, DEF_TOKEN_LIMIT, &var_token_limit, 1, 0,
534
	VAR_TOKEN_LIMIT, DEF_TOKEN_LIMIT, &var_token_limit, 1, 0,
490
	VAR_MIME_MAXDEPTH, DEF_MIME_MAXDEPTH, &var_mime_maxdepth, 1, 0,
535
	VAR_MIME_MAXDEPTH, DEF_MIME_MAXDEPTH, &var_mime_maxdepth, 1, 0,
491
	VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0,
536
	VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0,
537
 	VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
538
 	VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0,
539
 	VAR_TLS_DAEMON_RAND_BYTES, DEF_TLS_DAEMON_RAND_BYTES, &var_tls_daemon_rand_bytes, 0, 0,
492
	0,
540
	0,
493
    };
541
    };
494
    static CONFIG_TIME_TABLE time_defaults[] = {
542
    static CONFIG_TIME_TABLE time_defaults[] = {
Lines 499-504 Link Here
499
	VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0,
547
	VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0,
500
	VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0,
548
	VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0,
501
	VAR_FLOCK_STALE, DEF_FLOCK_STALE, &var_flock_stale, 1, 0,
549
	VAR_FLOCK_STALE, DEF_FLOCK_STALE, &var_flock_stale, 1, 0,
550
	VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, 0,
551
	VAR_SMTP_TLS_SCACHTIME, DEF_SMTP_TLS_SCACHTIME, &var_smtp_tls_scache_timeout, 0, 0,
502
	VAR_DAEMON_TIMEOUT, DEF_DAEMON_TIMEOUT, &var_daemon_timeout, 1, 0,
552
	VAR_DAEMON_TIMEOUT, DEF_DAEMON_TIMEOUT, &var_daemon_timeout, 1, 0,
503
	VAR_IN_FLOW_DELAY, DEF_IN_FLOW_DELAY, &var_in_flow_delay, 0, 10,
553
	VAR_IN_FLOW_DELAY, DEF_IN_FLOW_DELAY, &var_in_flow_delay, 0, 10,
504
	0,
554
	0,
(-)postfix-1.1.11.20020613-orig/src/global/mail_params.h (+202 lines)
Lines 458-463 Link Here
458
#define DEF_DUP_FILTER_LIMIT	1000
458
#define DEF_DUP_FILTER_LIMIT	1000
459
extern int var_dup_filter_limit;
459
extern int var_dup_filter_limit;
460
460
461
#define VAR_TLS_RAND_EXCH_NAME	"tls_random_exchange_name"
462
#define DEF_TLS_RAND_EXCH_NAME	"${config_directory}/prng_exch"
463
extern char *var_tls_rand_exch_name;
464
465
#define VAR_TLS_RAND_SOURCE	"tls_random_source"
466
#define DEF_TLS_RAND_SOURCE	""
467
extern char *var_tls_rand_source;
468
469
#define VAR_TLS_RAND_BYTES	"tls_random_bytes"
470
#define DEF_TLS_RAND_BYTES	32
471
extern int var_tls_rand_bytes;
472
473
#define VAR_TLS_DAEMON_RAND_SOURCE	"tls_daemon_random_source"
474
#define DEF_TLS_DAEMON_RAND_SOURCE	""
475
extern char *var_tls_daemon_rand_source;
476
477
#define VAR_TLS_DAEMON_RAND_BYTES	"tls_daemon_random_bytes"
478
#define DEF_TLS_DAEMON_RAND_BYTES	32
479
extern int var_tls_daemon_rand_bytes;
480
481
#define VAR_TLS_RESEED_PERIOD	"tls_random_reseed_period"
482
#define DEF_TLS_RESEED_PERIOD	"3600s"
483
extern int var_tls_reseed_period;
484
485
#define VAR_TLS_PRNG_UPD_PERIOD	"tls_random_prng_update_period"
486
#define DEF_TLS_PRNG_UPD_PERIOD "60s"
487
extern int var_tls_prng_upd_period;
488
461
 /*
489
 /*
462
  * Queue manager: relocated databases.
490
  * Queue manager: relocated databases.
463
  */
491
  */
Lines 678-683 Link Here
678
#define DEF_SMTP_HELO_TMOUT	"300s"
706
#define DEF_SMTP_HELO_TMOUT	"300s"
679
extern int var_smtp_helo_tmout;
707
extern int var_smtp_helo_tmout;
680
708
709
#define VAR_SMTP_STARTTLS_TMOUT	"smtp_starttls_timeout"
710
#define DEF_SMTP_STARTTLS_TMOUT	"300s"
711
extern int var_smtp_starttls_tmout;
712
681
#define VAR_SMTP_MAIL_TMOUT	"smtp_mail_timeout"
713
#define VAR_SMTP_MAIL_TMOUT	"smtp_mail_timeout"
682
#define DEF_SMTP_MAIL_TMOUT	"300s"
714
#define DEF_SMTP_MAIL_TMOUT	"300s"
683
extern int var_smtp_mail_tmout;
715
extern int var_smtp_mail_tmout;
Lines 734-739 Link Here
734
#define DEF_SMTP_BIND_ADDR	""
766
#define DEF_SMTP_BIND_ADDR	""
735
extern char *var_smtp_bind_addr;
767
extern char *var_smtp_bind_addr;
736
768
769
#ifdef INET6
770
#define VAR_SMTP_BIND_ADDR6	"smtp_bind_address6"
771
#define DEF_SMTP_BIND_ADDR6	""
772
extern char *var_smtp_bind_addr6;
773
#endif
774
737
#define VAR_SMTP_HELO_NAME	"smtp_helo_name"
775
#define VAR_SMTP_HELO_NAME	"smtp_helo_name"
738
#define DEF_SMTP_HELO_NAME	"$myhostname"
776
#define DEF_SMTP_HELO_NAME	"$myhostname"
739
extern char *var_smtp_helo_name;
777
extern char *var_smtp_helo_name;
Lines 767-772 Link Here
767
#define DEF_SMTPD_TMOUT		"300s"
805
#define DEF_SMTPD_TMOUT		"300s"
768
extern int var_smtpd_tmout;
806
extern int var_smtpd_tmout;
769
807
808
#define VAR_SMTPD_STARTTLS_TMOUT "smtpd_starttls_timeout"
809
#define DEF_SMTPD_STARTTLS_TMOUT "300s"
810
extern int var_smtpd_starttls_tmout;
811
770
#define VAR_SMTPD_RCPT_LIMIT	"smtpd_recipient_limit"
812
#define VAR_SMTPD_RCPT_LIMIT	"smtpd_recipient_limit"
771
#define DEF_SMTPD_RCPT_LIMIT	1000
813
#define DEF_SMTPD_RCPT_LIMIT	1000
772
extern int var_smtpd_rcpt_limit;
814
extern int var_smtpd_rcpt_limit;
Lines 795-800 Link Here
795
#define DEF_SMTPD_NOOP_CMDS	""
837
#define DEF_SMTPD_NOOP_CMDS	""
796
extern char *var_smtpd_noop_cmds;
838
extern char *var_smtpd_noop_cmds;
797
839
840
#define VAR_SMTPD_TLS_WRAPPER	"smtpd_tls_wrappermode"
841
#define DEF_SMTPD_TLS_WRAPPER	0
842
extern bool var_smtpd_tls_wrappermode;
843
844
#define VAR_SMTPD_USE_TLS	"smtpd_use_tls"
845
#define DEF_SMTPD_USE_TLS	0
846
extern bool var_smtpd_use_tls;
847
848
#define VAR_SMTPD_ENFORCE_TLS	"smtpd_enforce_tls"
849
#define DEF_SMTPD_ENFORCE_TLS	0
850
extern bool var_smtpd_enforce_tls;
851
852
#define VAR_SMTPD_TLS_AUTH_ONLY	"smtpd_tls_auth_only"
853
#define DEF_SMTPD_TLS_AUTH_ONLY 0
854
extern bool var_smtpd_tls_auth_only;
855
856
#define VAR_SMTPD_TLS_ACERT	"smtpd_tls_ask_ccert"
857
#define DEF_SMTPD_TLS_ACERT	0
858
extern bool var_smtpd_tls_ask_ccert;
859
860
#define VAR_SMTPD_TLS_RCERT	"smtpd_tls_req_ccert"
861
#define DEF_SMTPD_TLS_RCERT	0
862
extern bool var_smtpd_tls_req_ccert;
863
864
#define VAR_SMTPD_TLS_CCERT_VD	"smtpd_tls_ccert_verifydepth"
865
#define DEF_SMTPD_TLS_CCERT_VD	5
866
extern int var_smtpd_tls_ccert_vd;
867
868
#define VAR_SMTPD_TLS_CERT_FILE	"smtpd_tls_cert_file"
869
#define DEF_SMTPD_TLS_CERT_FILE	""
870
extern char *var_smtpd_tls_cert_file;
871
872
#define VAR_SMTPD_TLS_KEY_FILE	"smtpd_tls_key_file"
873
#define DEF_SMTPD_TLS_KEY_FILE	"$smtpd_tls_cert_file"
874
extern char *var_smtpd_tls_key_file;
875
876
#define VAR_SMTPD_TLS_DCERT_FILE "smtpd_tls_dcert_file"
877
#define DEF_SMTPD_TLS_DCERT_FILE ""
878
extern char *var_smtpd_tls_dcert_file;
879
880
#define VAR_SMTPD_TLS_DKEY_FILE	"smtpd_tls_dkey_file"
881
#define DEF_SMTPD_TLS_DKEY_FILE	"$smtpd_tls_dcert_file"
882
extern char *var_smtpd_tls_dkey_file;
883
884
#define VAR_SMTPD_TLS_CA_FILE	"smtpd_tls_CAfile"
885
#define DEF_SMTPD_TLS_CA_FILE	""
886
extern char *var_smtpd_tls_CAfile;
887
888
#define VAR_SMTPD_TLS_CA_PATH	"smtpd_tls_CApath"
889
#define DEF_SMTPD_TLS_CA_PATH	""
890
extern char *var_smtpd_tls_CApath;
891
892
#define VAR_SMTPD_TLS_CLIST	"smtpd_tls_cipherlist"
893
#define DEF_SMTPD_TLS_CLIST	""
894
extern char *var_smtpd_tls_cipherlist;
895
896
#define VAR_SMTPD_TLS_512_FILE	"smtpd_tls_dh512_param_file"
897
#define DEF_SMTPD_TLS_512_FILE	""
898
extern char *var_smtpd_tls_dh512_param_file;
899
900
#define VAR_SMTPD_TLS_1024_FILE	"smtpd_tls_dh1024_param_file"
901
#define DEF_SMTPD_TLS_1024_FILE	""
902
extern char *var_smtpd_tls_dh1024_param_file;
903
904
#define VAR_SMTPD_TLS_LOGLEVEL	"smtpd_tls_loglevel"
905
#define DEF_SMTPD_TLS_LOGLEVEL	0
906
extern int var_smtpd_tls_loglevel;
907
908
#define VAR_SMTPD_TLS_RECHEAD	"smtpd_tls_received_header"
909
#define DEF_SMTPD_TLS_RECHEAD	0
910
extern bool var_smtpd_tls_received_header;
911
912
#define VAR_SMTPD_TLS_SCACHE_DB	"smtpd_tls_session_cache_database"
913
#define DEF_SMTPD_TLS_SCACHE_DB	""
914
extern char *var_smtpd_tls_scache_db;
915
916
#define VAR_SMTPD_TLS_SCACHTIME	"smtpd_tls_session_cache_timeout"
917
#define DEF_SMTPD_TLS_SCACHTIME	"3600s"
918
extern int var_smtpd_tls_scache_timeout;
919
920
#define VAR_SMTP_TLS_PER_SITE	"smtp_tls_per_site"
921
#define DEF_SMTP_TLS_PER_SITE	""
922
extern char *var_smtp_tls_per_site;
923
924
#define VAR_SMTP_USE_TLS	"smtp_use_tls"
925
#define DEF_SMTP_USE_TLS	0
926
extern bool var_smtp_use_tls;
927
928
#define VAR_SMTP_ENFORCE_TLS	"smtp_enforce_tls"
929
#define DEF_SMTP_ENFORCE_TLS	0
930
extern bool var_smtp_enforce_tls;
931
932
#define VAR_SMTP_TLS_ENFORCE_PN	"smtp_tls_enforce_peername"
933
#define DEF_SMTP_TLS_ENFORCE_PN	1
934
extern bool var_smtp_tls_enforce_peername;
935
936
#define VAR_SMTP_TLS_SCERT_VD	"smtp_tls_scert_verifydepth"
937
#define DEF_SMTP_TLS_SCERT_VD	5
938
extern int var_smtp_tls_scert_vd;
939
940
#define VAR_SMTP_TLS_CERT_FILE	"smtp_tls_cert_file"
941
#define DEF_SMTP_TLS_CERT_FILE	""
942
extern char *var_smtp_tls_cert_file;
943
944
#define VAR_SMTP_TLS_KEY_FILE	"smtp_tls_key_file"
945
#define DEF_SMTP_TLS_KEY_FILE	"$smtp_tls_cert_file"
946
extern char *var_smtp_tls_key_file;
947
948
#define VAR_SMTP_TLS_DCERT_FILE "smtp_tls_dcert_file"
949
#define DEF_SMTP_TLS_DCERT_FILE ""
950
extern char *var_smtp_tls_dcert_file;
951
952
#define VAR_SMTP_TLS_DKEY_FILE	"smtp_tls_dkey_file"
953
#define DEF_SMTP_TLS_DKEY_FILE	"$smtp_tls_dcert_file"
954
extern char *var_smtp_tls_dkey_file;
955
956
#define VAR_SMTP_TLS_CA_FILE	"smtp_tls_CAfile"
957
#define DEF_SMTP_TLS_CA_FILE	""
958
extern char *var_smtp_tls_CAfile;
959
960
#define VAR_SMTP_TLS_CA_PATH	"smtp_tls_CApath"
961
#define DEF_SMTP_TLS_CA_PATH	""
962
extern char *var_smtp_tls_CApath;
963
964
#define VAR_SMTP_TLS_CLIST	"smtp_tls_cipherlist"
965
#define DEF_SMTP_TLS_CLIST	""
966
extern char *var_smtp_tls_cipherlist;
967
968
#define VAR_SMTP_TLS_LOGLEVEL	"smtp_tls_loglevel"
969
#define DEF_SMTP_TLS_LOGLEVEL	0
970
extern int var_smtp_tls_loglevel;
971
972
#define VAR_SMTP_TLS_NOTEOFFER	"smtp_tls_note_starttls_offer"
973
#define DEF_SMTP_TLS_NOTEOFFER	0
974
extern bool var_smtp_tls_note_starttls_offer;
975
976
#define VAR_SMTP_TLS_SCACHE_DB	"smtp_tls_session_cache_database"
977
#define DEF_SMTP_TLS_SCACHE_DB	""
978
extern char *var_smtp_tls_scache_db;
979
980
#define VAR_SMTP_TLS_SCACHTIME	"smtp_tls_session_cache_timeout"
981
#define DEF_SMTP_TLS_SCACHTIME	"3600s"
982
extern int var_smtp_tls_scache_timeout;
983
798
 /*
984
 /*
799
  * SASL authentication support, SMTP server side.
985
  * SASL authentication support, SMTP server side.
800
  */
986
  */
Lines 953-958 Link Here
953
#define DEF_LMTP_QUIT_TMOUT	"300s"
1139
#define DEF_LMTP_QUIT_TMOUT	"300s"
954
extern int var_lmtp_quit_tmout;
1140
extern int var_lmtp_quit_tmout;
955
1141
1142
#define VAR_LMTP_BIND_ADDR	"lmtp_bind_address"
1143
#define DEF_LMTP_BIND_ADDR	""
1144
extern char *var_lmtp_bind_addr;
1145
1146
#ifdef INET6
1147
#define VAR_LMTP_BIND_ADDR6	"lmtp_bind_address6"
1148
#define DEF_LMTP_BIND_ADDR6	""
1149
extern char *var_lmtp_bind_addr6;
1150
#endif
1151
956
 /*
1152
 /*
957
  * Cleanup service. Header info that exceeds $header_size_limit bytes forces
1153
  * Cleanup service. Header info that exceeds $header_size_limit bytes forces
958
  * the start of the message body.
1154
  * the start of the message body.
Lines 1088-1093 Link Here
1088
#define DEF_RELAY_DOMAINS	"$mydestination"
1284
#define DEF_RELAY_DOMAINS	"$mydestination"
1089
extern char *var_relay_domains;
1285
extern char *var_relay_domains;
1090
1286
1287
#define VAR_RELAY_CCERTS	"relay_clientcerts"
1288
#define DEF_RELAY_CCERTS	""
1289
extern char *var_relay_ccerts;
1290
1091
#define VAR_CLIENT_CHECKS	"smtpd_client_restrictions"
1291
#define VAR_CLIENT_CHECKS	"smtpd_client_restrictions"
1092
#define DEF_CLIENT_CHECKS	""
1292
#define DEF_CLIENT_CHECKS	""
1093
extern char *var_client_checks;
1293
extern char *var_client_checks;
Lines 1167-1172 Link Here
1167
#define PERMIT_AUTH_DEST	"permit_auth_destination"
1367
#define PERMIT_AUTH_DEST	"permit_auth_destination"
1168
#define REJECT_UNAUTH_DEST	"reject_unauth_destination"
1368
#define REJECT_UNAUTH_DEST	"reject_unauth_destination"
1169
#define CHECK_RELAY_DOMAINS	"check_relay_domains"
1369
#define CHECK_RELAY_DOMAINS	"check_relay_domains"
1370
#define PERMIT_TLS_CLIENTCERTS	"permit_tls_clientcerts"
1371
#define PERMIT_TLS_ALL_CLIENTCERTS	"permit_tls_all_clientcerts"
1170
#define VAR_RELAY_CODE		"relay_domains_reject_code"
1372
#define VAR_RELAY_CODE		"relay_domains_reject_code"
1171
#define DEF_RELAY_CODE		554
1373
#define DEF_RELAY_CODE		554
1172
extern int var_relay_code;
1374
extern int var_relay_code;
(-)postfix-1.1.11.20020613-orig/src/global/mail_proto.h (+1 lines)
Lines 34-39 Link Here
34
#define MAIL_SERVICE_LOCAL	"local"
34
#define MAIL_SERVICE_LOCAL	"local"
35
#define MAIL_SERVICE_PICKUP	"pickup"
35
#define MAIL_SERVICE_PICKUP	"pickup"
36
#define MAIL_SERVICE_QUEUE	"qmgr"
36
#define MAIL_SERVICE_QUEUE	"qmgr"
37
#define MAIL_SERVICE_TLSMGR	"tlsmgr"
37
#define MAIL_SERVICE_RESOLVE	"resolve"
38
#define MAIL_SERVICE_RESOLVE	"resolve"
38
#define MAIL_SERVICE_REWRITE	"rewrite"
39
#define MAIL_SERVICE_REWRITE	"rewrite"
39
#define MAIL_SERVICE_VIRTUAL	"virtual"
40
#define MAIL_SERVICE_VIRTUAL	"virtual"
(-)postfix-1.1.11.20020613-orig/src/global/mynetworks.c (+29 lines)
Lines 50-55 Link Here
50
#include <vstring.h>
50
#include <vstring.h>
51
#include <inet_addr_list.h>
51
#include <inet_addr_list.h>
52
#include <name_mask.h>
52
#include <name_mask.h>
53
#ifdef INET6
54
#include <sys/socket.h>
55
#include <netinet/in.h>
56
#include <netdb.h>
57
#endif
53
58
54
/* Global library. */
59
/* Global library. */
55
60
Lines 75-80 Link Here
75
const char *mynetworks(void)
80
const char *mynetworks(void)
76
{
81
{
77
    static VSTRING *result;
82
    static VSTRING *result;
83
#ifdef INET6
84
    char hbuf[NI_MAXHOST];
85
#endif
78
86
79
    if (result == 0) {
87
    if (result == 0) {
80
	char   *myname = "mynetworks";
88
	char   *myname = "mynetworks";
Lines 87-92 Link Here
87
	int     junk;
95
	int     junk;
88
	int     i;
96
	int     i;
89
	int     mask_style;
97
	int     mask_style;
98
#ifdef INET6
99
	struct sockaddr *sa;
100
#endif
90
101
91
	mask_style = name_mask("mynetworks mask style", mask_styles,
102
	mask_style = name_mask("mynetworks mask style", mask_styles,
92
			       var_mynetworks_style);
103
			       var_mynetworks_style);
Lines 96-103 Link Here
96
	my_mask_list = own_inet_mask_list();
107
	my_mask_list = own_inet_mask_list();
97
108
98
	for (i = 0; i < my_addr_list->used; i++) {
109
	for (i = 0; i < my_addr_list->used; i++) {
110
#ifdef INET6
111
	    sa = (struct sockaddr *)&my_addr_list->addrs[i];
112
	    if (sa->sa_family != AF_INET) {
113
		if (sa->sa_family == AF_INET6)
114
		    vstring_sprintf_append(result, "XAATODOmynetworks ");
115
		continue;
116
	    }
117
	    addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
118
	    mask = ntohl(((struct sockaddr_in *)&my_mask_list->addrs[i])->sin_addr.s_addr);
119
#else
99
	    addr = ntohl(my_addr_list->addrs[i].s_addr);
120
	    addr = ntohl(my_addr_list->addrs[i].s_addr);
100
	    mask = ntohl(my_mask_list->addrs[i].s_addr);
121
	    mask = ntohl(my_mask_list->addrs[i].s_addr);
122
#endif
101
123
102
	    switch (mask_style) {
124
	    switch (mask_style) {
103
125
Lines 119-126 Link Here
119
		    mask = IN_CLASSD_NET;
141
		    mask = IN_CLASSD_NET;
120
		    shift = IN_CLASSD_NSHIFT;
142
		    shift = IN_CLASSD_NSHIFT;
121
		} else {
143
		} else {
144
#ifdef INET6
145
		    if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
146
			    NI_NUMERICHOST))
147
			strncpy(hbuf, "???", sizeof(hbuf));
148
		    msg_fatal("%s: bad address class: %s", myname, hbuf);
149
#else
122
		    msg_fatal("%s: bad address class: %s",
150
		    msg_fatal("%s: bad address class: %s",
123
			      myname, inet_ntoa(my_addr_list->addrs[i]));
151
			      myname, inet_ntoa(my_addr_list->addrs[i]));
152
#endif
124
		}
153
		}
125
		break;
154
		break;
126
155
(-)postfix-1.1.11.20020613-orig/src/global/own_inet_addr.c (-3 / +68 lines)
Lines 39-44 Link Here
39
#include <netinet/in.h>
39
#include <netinet/in.h>
40
#include <arpa/inet.h>
40
#include <arpa/inet.h>
41
#include <string.h>
41
#include <string.h>
42
#ifdef INET6
43
#include <sys/socket.h>
44
#include <netdb.h>
45
#endif
42
46
43
#ifdef STRCASECMP_IN_STRINGS_H
47
#ifdef STRCASECMP_IN_STRINGS_H
44
#include <strings.h>
48
#include <strings.h>
Lines 101-110 Link Here
101
     */
105
     */
102
    else {
106
    else {
103
	bufp = hosts = mystrdup(var_inet_interfaces);
107
	bufp = hosts = mystrdup(var_inet_interfaces);
104
	while ((host = mystrtok(&bufp, sep)) != 0)
108
	while ((host = mystrtok(&bufp, sep)) != 0) {
105
	    if (inet_addr_host(addr_list, host) == 0)
109
	    if (inet_addr_host(addr_list, host) == 0)
106
		msg_fatal("config variable %s: host not found: %s",
110
		msg_fatal("config variable %s: host not found: %s",
107
			  VAR_INET_INTERFACES, host);
111
			  VAR_INET_INTERFACES, host);
112
	}
108
	myfree(hosts);
113
	myfree(hosts);
109
114
110
	/*
115
	/*
Lines 121-135 Link Here
121
	    msg_fatal("could not find any active network interfaces");
126
	    msg_fatal("could not find any active network interfaces");
122
	for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
127
	for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
123
	    for (nlocal = 0; /* see below */ ; nlocal++) {
128
	    for (nlocal = 0; /* see below */ ; nlocal++) {
124
		if (nlocal >= local_addrs.used)
129
		if (nlocal >= local_addrs.used) {
130
#ifdef INET6
131
		    char hbuf[NI_MAXHOST];
132
		    if (getnameinfo((struct sockaddr *)&addr_list->addrs[nvirtual],
133
		        SS_LEN(addr_list->addrs[nvirtual]), hbuf,
134
		        sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
135
			strncpy(hbuf, "???", sizeof(hbuf));
136
		    msg_fatal("parameter %s: no local interface found for %s",
137
			      VAR_INET_INTERFACES, hbuf);
138
#else
125
		    msg_fatal("parameter %s: no local interface found for %s",
139
		    msg_fatal("parameter %s: no local interface found for %s",
126
			      VAR_INET_INTERFACES,
140
			      VAR_INET_INTERFACES,
127
			      inet_ntoa(addr_list->addrs[nvirtual]));
141
			      inet_ntoa(addr_list->addrs[nvirtual]));
142
#endif
143
		}
144
#ifdef INET6
145
		if (addr_list->addrs[nvirtual].ss_family == 
146
		    local_addrs.addrs[nlocal].ss_family &&
147
		    SS_LEN(addr_list->addrs[nvirtual]) == 
148
		    SS_LEN(local_addrs.addrs[nlocal]) &&
149
		    memcmp(&addr_list->addrs[nvirtual],
150
		    &local_addrs.addrs[nlocal],
151
		    SS_LEN(local_addrs.addrs[nlocal])) == 0) {
152
		    inet_addr_list_append(mask_list, (struct sockaddr *)&local_masks.addrs[nlocal]);
153
		    break;
154
		}
155
#else
128
		if (addr_list->addrs[nvirtual].s_addr
156
		if (addr_list->addrs[nvirtual].s_addr
129
		    == local_addrs.addrs[nlocal].s_addr) {
157
		    == local_addrs.addrs[nlocal].s_addr) {
130
		    inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]);
158
		    inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]);
131
		    break;
159
		    break;
132
		}
160
		}
161
#endif
133
	    }
162
	    }
134
	}
163
	}
135
	inet_addr_list_free(&local_addrs);
164
	inet_addr_list_free(&local_addrs);
Lines 139-144 Link Here
139
168
140
/* own_inet_addr - is this my own internet address */
169
/* own_inet_addr - is this my own internet address */
141
170
171
#ifdef INET6
172
int     own_inet_addr(struct sockaddr * addr)
173
{
174
    int     i;
175
    char *p, *q;
176
    int l;
177
    struct sockaddr *sa;
178
179
    if (addr_list.used == 0)
180
	own_inet_addr_init(&addr_list, &mask_list);
181
182
    for (i = 0; i < addr_list.used; i++) {
183
	sa = (struct sockaddr *)&addr_list.addrs[i];
184
	if (addr->sa_family != sa->sa_family)
185
	    continue;
186
	switch (addr->sa_family) {
187
	case AF_INET:
188
	    p = (char *)&((struct sockaddr_in *)addr)->sin_addr;
189
	    q = (char *)&((struct sockaddr_in *)&addr_list.addrs[i])->sin_addr;
190
	    l = sizeof(struct in_addr);
191
	    break;
192
	case AF_INET6:
193
	    /* XXX scope */
194
	    p = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
195
	    q = (char *)&((struct sockaddr_in6 *)&addr_list.addrs[i])->sin6_addr;
196
	    l = sizeof(struct in6_addr);
197
	    break;
198
	default:
199
	    continue;
200
	}
201
	if (memcmp(p, q, l) == 0)
202
	    return (1);
203
    }
204
    return (0);
205
}
206
#else
142
int     own_inet_addr(struct in_addr * addr)
207
int     own_inet_addr(struct in_addr * addr)
143
{
208
{
144
    int     i;
209
    int     i;
Lines 149-156 Link Here
149
    for (i = 0; i < addr_list.used; i++)
214
    for (i = 0; i < addr_list.used; i++)
150
	if (addr->s_addr == addr_list.addrs[i].s_addr)
215
	if (addr->s_addr == addr_list.addrs[i].s_addr)
151
	    return (1);
216
	    return (1);
152
    return (0);
153
}
217
}
218
#endif
154
219
155
/* own_inet_addr_list - return list of addresses */
220
/* own_inet_addr_list - return list of addresses */
156
221
(-)postfix-1.1.11.20020613-orig/src/global/own_inet_addr.h (+7 lines)
Lines 15-25 Link Here
15
  * System library.
15
  * System library.
16
  */
16
  */
17
#include <netinet/in.h>
17
#include <netinet/in.h>
18
#ifdef INET6
19
#include <sys/socket.h>
20
#endif
18
21
19
 /*
22
 /*
20
  * External interface.
23
  * External interface.
21
  */
24
  */
25
#ifdef INET6
26
extern int own_inet_addr(struct sockaddr *);
27
#else
22
extern int own_inet_addr(struct in_addr *);
28
extern int own_inet_addr(struct in_addr *);
29
#endif
23
extern struct INET_ADDR_LIST *own_inet_addr_list(void);
30
extern struct INET_ADDR_LIST *own_inet_addr_list(void);
24
extern struct INET_ADDR_LIST *own_inet_mask_list(void);
31
extern struct INET_ADDR_LIST *own_inet_mask_list(void);
25
32
(-)postfix-1.1.11.20020613-orig/src/global/peer_name.c (-4 / +42 lines)
Lines 69-80 Link Here
69
PEER_NAME *peer_name(int sock)
69
PEER_NAME *peer_name(int sock)
70
{
70
{
71
    static PEER_NAME peer;
71
    static PEER_NAME peer;
72
    struct sockaddr_in sin;
72
    union sockunion {
73
    SOCKADDR_SIZE len = sizeof(sin);
73
	struct {
74
	    u_char si_len;
75
	    u_char si_family;
76
	    u_short si_port;
77
	} su_si;
78
	struct sockaddr peer_un;
79
	struct sockaddr_in peer_un4;
80
#ifdef INET6
81
	struct sockaddr_in6 peer_un6;
82
#endif
83
    } p_un;
84
#define sun p_un.peer_un
85
#define sin p_un.peer_un4
86
#ifdef INET6
87
#define sin6 p_un.peer_un6
88
    static char hbuf[NI_MAXHOST];
89
    static char abuf[NI_MAXHOST];
90
#else
74
    struct hostent *hp;
91
    struct hostent *hp;
92
#endif
93
    SOCKADDR_SIZE len = sizeof(p_un);
75
94
76
    if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) {
95
    if (getpeername(sock, (struct sockaddr *)&p_un, &len) == 0) {
77
	switch (sin.sin_family) {
96
	switch (p_un.peer_un.sa_family) {
97
#ifndef INET6
78
	case AF_INET:
98
	case AF_INET:
79
	    peer.type = PEER_TYPE_INET;
99
	    peer.type = PEER_TYPE_INET;
80
	    hp = gethostbyaddr((char *) &(sin.sin_addr),
100
	    hp = gethostbyaddr((char *) &(sin.sin_addr),
Lines 83-88 Link Here
83
			 hp->h_name : "unknown");
103
			 hp->h_name : "unknown");
84
	    peer.addr = inet_ntoa(sin.sin_addr);
104
	    peer.addr = inet_ntoa(sin.sin_addr);
85
	    return (&peer);
105
	    return (&peer);
106
#else
107
	case AF_INET:
108
	    peer.type = PEER_TYPE_INET;
109
	    if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
110
		peer.name = "unknown";
111
	    else
112
		peer.name = hbuf;
113
	    peer.addr = abuf;
114
	    return (&peer);
115
	case AF_INET6:
116
	    peer.type = PEER_TYPE_INET6;
117
	    if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
118
		peer.name = "unknown";
119
	    else
120
		peer.name = hbuf;
121
	    peer.addr = abuf;
122
	    return (&peer);
123
#endif
86
	case AF_UNSPEC:
124
	case AF_UNSPEC:
87
	case AF_UNIX:
125
	case AF_UNIX:
88
	    peer.type = PEER_TYPE_LOCAL;
126
	    peer.type = PEER_TYPE_LOCAL;
(-)postfix-1.1.11.20020613-orig/src/global/peer_name.h (+3 lines)
Lines 22-27 Link Here
22
#define PEER_TYPE_UNKNOWN	0
22
#define PEER_TYPE_UNKNOWN	0
23
#define PEER_TYPE_INET		1
23
#define PEER_TYPE_INET		1
24
#define PEER_TYPE_LOCAL		2
24
#define PEER_TYPE_LOCAL		2
25
#ifdef INET6
26
#define PEER_TYPE_INET6		3
27
#endif
25
28
26
extern PEER_NAME *peer_name(int);
29
extern PEER_NAME *peer_name(int);
27
30
(-)postfix-1.1.11.20020613-orig/src/global/pfixtls.c (+2742 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*	pfixtls
4
/* SUMMARY
5
/*	interface to openssl routines
6
/* SYNOPSIS
7
/*	#include <pfixtls.h>
8
/*
9
/*	const long scache_db_version;
10
/*	const long openssl_version;
11
/*
12
/*	int pfixtls_serverengine;
13
/*
14
/*	int pfixtls_clientengine;
15
/*
16
/*	int pfixtls_timed_read(fd, buf, len, timeout, unused_context)
17
/*	int fd;
18
/*	void *buf;
19
/*	unsigned len;
20
/*	int timeout;
21
/*	void *context;
22
/*
23
/*	int pfixtls_timed_write(fd, buf, len, timeout, unused_context);
24
/*	int fd;
25
/*	void *buf;
26
/*	unsigned len;
27
/*	int timeout;
28
/*	void *context;
29
/*
30
/*	int pfixtls_init_serverengine(verifydepth, askcert);
31
/*	int verifydepth;
32
/*	int askcert;
33
/*
34
/*	int pfixtls_start_servertls(stream, timeout, peername, peeraddr,
35
/*				    tls_info, requirecert);
36
/*	VSTREAM *stream;
37
/*	int timeout;
38
/*	const char *peername;
39
/*	const char *peeraddr;
40
/*	tls_info_t *tls_info;
41
/*	int requirecert;
42
/*
43
/*	int pfixtls_stop_servertls(stream, failure, tls_info);
44
/*	VSTREAM *stream;
45
/*	int failure;
46
/*	tls_info_t *tls_info;
47
/*	
48
/*	int pfixtls_init_clientengine(verifydepth);
49
/*	int verifydepth;
50
/*
51
/*	int pfixtls_start_clienttls(stream, timeout, peername, peeraddr,
52
/*				    tls_info);
53
/*	VSTREAM *stream;
54
/*	int timeout;
55
/*	const char *peername;
56
/*	const char *peeraddr;
57
/*	tls_info_t *tls_info;
58
/*
59
/*	int pfixtls_stop_clienttls(stream, failure, tls_info);
60
/*	VSTREAM *stream;
61
/*	int failure;
62
/*	tls_info_t *tls_info;
63
/*
64
/* DESCRIPTION
65
/*	This module is the interface between Postfix and the OpenSSL library.
66
/*
67
/*	pfixtls_timed_read() reads the requested number of bytes calling
68
/*	SSL_read(). pfixtls_time_read() will only be called indirect
69
/*	as a VSTREAM_FN function.
70
/*	pfixtls_timed_write() is the corresponding write function.
71
/*
72
/*	pfixtls_init_serverengine() is called once when smtpd is started
73
/*	in order to initialize as much of the TLS stuff as possible.
74
/*	The certificate handling is also decided during the setup phase,
75
/*	so that a peer specific handling is not possible.
76
/*
77
/*	pfixtls_init_clientengine() is the corresponding function called
78
/*	in smtp. Here we take the peer's (server's) certificate in any
79
/*	case.
80
/*
81
/*	pfixtls_start_servertls() activates the TLS feature for the VSTREAM
82
/*	passed as argument. We expect that all buffers are flushed and the
83
/*	TLS handshake can begin	immediately. Information about the peer
84
/*	is stored into the tls_info structure passed as argument.
85
/*
86
/*	pfixtls_stop_servertls() sends the "close notify" alert via
87
/*	SSL_shutdown() to the peer and resets all connection specific
88
/*	TLS data. As RFC2487 does not specify a seperate shutdown, it
89
/*	is supposed that the underlying TCP connection is shut down
90
/*	immediately afterwards, so we don't care about additional data
91
/*	coming through the channel.
92
/*	If the failure flag is set, the session is cleared from the cache.
93
/*
94
/*	pfixtls_start_clienttls() and pfixtls_stop_clienttls() are the
95
/*	corresponding functions for smtp.
96
/*
97
/*	Once the TLS connection is initiated, information about the TLS
98
/*	state is available via the tls_info structure:
99
/*	protocol holds the protocol name (SSLv2, SSLv3, TLSv1),
100
/*	tls_info->cipher_name the cipher name (e.g. RC4/MD5),
101
/*	tls_info->cipher_usebits the number of bits actually used (e.g. 40),
102
/*	tls_info->cipher_algbits the number of bits the algorithm is based on
103
/*	(e.g. 128).
104
/*	The last two values may be different when talking to a crippled
105
/*	- ahem - export controled peer (e.g. 40/128).
106
/*
107
/*	The status of the peer certificate verification is available in
108
/*	pfixtls_peer_verified. It is set to 1, when the certificate could
109
/*	be verified.
110
/*	If the peer offered a certifcate, part of the certificate data are
111
/*	available as:
112
/*	tls_info->peer_subject X509v3-oneline with the DN of the peer
113
/*	tls_info->peer_CN extracted CommonName of the peer
114
/*	tls_info->peer_issuer  X509v3-oneline with the DN of the issuer
115
/*	tls_info->peer_CN extracted CommonName of the issuer
116
/*	tls_info->PEER_FINGERPRINT fingerprint of the certificate
117
/*
118
/* DESCRIPTION (SESSION CACHING)
119
/*	In order to achieve high performance when using a lot of connections
120
/*	with TLS, session caching is implemented. It reduces both the CPU load
121
/*	(less cryptograpic operations) and the network load (the amount of
122
/*	certificate data exchanged is reduced).
123
/*	Since postfix uses a setup of independent processes for receiving
124
/*	and sending email, the processes must exchange the session information.
125
/*	Several connections at the same time between the identical peers can
126
/*	occur, so uniqueness and race conditions have to be taken into
127
/*	account.
128
/*	I have checked both Apache-SSL (Ben Laurie), using a seperate "gcache"
129
/*	process and Apache mod_ssl (Ralf S. Engelshall), using shared memory
130
/*	between several identical processes spawned from one parent.
131
/*
132
/*	Postfix/TLS uses a database approach based on the internal "dict"
133
/*	interface. Since the session cache information is approximately
134
/*	1300 bytes binary data, it will not fit into the dbm/ndbm model.
135
/*	It also needs write access to the database, ruling out most other
136
/*	interface, leaving Berkeley DB, which however cannot handle concurrent
137
/*	access by several processes. Hence a modified SDBM (public domain DBM)
138
/*	with enhanced buffer size is used and concurrent write capability
139
/*	is used. SDBM is part of Postfix/TLS.
140
/*
141
/*	Realization:
142
/*	Both (client and server) session cache are realized by individual
143
/*	cache databases. A common database would not make sense, since the
144
/*	key criteria are different (session ID for server, peername for
145
/*	client).
146
/*
147
/*	Server side:
148
/*	Session created by OpenSSL have a 32 byte session id, yielding a
149
/*	64 char file name. I consider these sessions to be unique. If they
150
/*	are not, the last session will win, overwriting the older one in
151
/*	the database. Remember: everything that is lost is a temporary
152
/*	information and not more than a renegotiation will happen.
153
/*	Originating from the same client host, several sessions can come
154
/*	in (e.g. from several users sending mail with Netscape at the same
155
/*	time), so the session id is the correct identifier; the hostname
156
/*	is of no importance, here.
157
/*
158
/*	Client side:
159
/*	We cannot recall sessions based on their session id, because we would
160
/*	have to check every session on disk for a matching server name, so
161
/*	the lookup has to be done based on the FQDN of the peer (receiving
162
/*	host).
163
/*	With regard to uniqueness, we might experience several open connections
164
/*	to the same server at the same time. This is even very likely to
165
/*	happen, since we might have several mails for the same destination
166
/*	in the queue, when a queue run is started. So several smtp's might
167
/*	negotiate sessions at the same time. We can however only save one
168
/*	session for one host.
169
/*	Like on the server side, the "last write" wins. The reason is
170
/*	quite simple. If we don't want to overwrite old sessions, an old
171
/*	session file will just stay in place until it is expired. In the
172
/*	meantime we would lose "fresh" session however. So we will keep the
173
/*	fresh one instead to avoid unnecessary renegotiations.
174
/*
175
/*	Session lifetime:
176
/*	RFC2246 recommends a session lifetime of less than 24 hours. The
177
/*	default is 300 seconds (5 minutes) for OpenSSL and is also used
178
/*	this way in e.g. mod_ssl. The typical usage for emails might be
179
/*	humans typing in emails and sending them, which might take just
180
/*	a while, so I think 3600 seconds (1 hour) is a good compromise.
181
/*	If the environment is save (the cached session contains secret
182
/*	key data), one might even consider using a longer timeout. Anyway,
183
/*	since everlasting sessions must be avoided, the session timeout
184
/*	is done based on the creation date of the session and so each
185
/*	session will timeout eventually.
186
/*
187
/*	Connection failures:
188
/*	RFC2246 requires us to remove sessions if something went wrong.
189
/*	Since the in-memory session cache of other smtp[d] processes cannot
190
/*	be controlled by simple means, we completely rely on the disc
191
/*	based session caching and remove all sessions from memory after
192
/*	connection closure.
193
/*
194
/*	Cache cleanup:
195
/*	Since old entries have to be removed from the session cache, a
196
/*	cleanup process is needed that runs through the collected session
197
/*	files on regular basis. The task is performed by tlsmgr based on
198
/*	the timestamp created by pfixtls and included in the saved session,
199
/*	so that tlsmgr has not to care about the SSL_SESSION internal data.
200
/*
201
/* BUGS
202
/*	The memory allocation policy of the OpenSSL library is not well
203
/*	documented, especially when loading sessions from disc. Hence there
204
/*	might be memory leaks.
205
/*
206
/* LICENSE
207
/* AUTHOR(S)
208
/*	Lutz Jaenicke
209
/*	BTU Cottbus
210
/*	Allgemeine Elektrotechnik
211
/*	Universitaetsplatz 3-4
212
/*	D-03044 Cottbus, Germany
213
/*--*/
214
215
/* System library. */
216
217
#include <sys_defs.h>
218
#include <sys/types.h>
219
#include <sys/stat.h>
220
#include <sys/time.h>			/* gettimeofday, not in POSIX */
221
#include <unistd.h>
222
#include <stdio.h>
223
#include <string.h>
224
#include <errno.h>
225
#include <ctype.h>
226
227
/* Utility library. */
228
229
#include <iostuff.h>
230
#include <mymalloc.h>
231
#include <vstring.h>
232
#include <vstream.h>
233
#include <dict.h>
234
#include <myflock.h>
235
#include <stringops.h>
236
#include <msg.h>
237
#include <connect.h>
238
239
/* Application-specific. */
240
241
#include "mail_params.h"
242
#include "pfixtls.h"
243
244
#define STR	vstring_str
245
246
const tls_info_t tls_info_zero = {
247
    0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
248
};
249
250
#ifdef HAS_SSL
251
252
/* OpenSSL library. */
253
254
#include <openssl/lhash.h>
255
#include <openssl/bn.h>
256
#include <openssl/err.h>
257
#include <openssl/pem.h>
258
#include <openssl/x509.h>
259
#include <openssl/rand.h>
260
#include <openssl/ssl.h>
261
262
/* We must keep some of the info available */
263
static const char hexcodes[] = "0123456789ABCDEF";
264
265
/*
266
 * When saving sessions, we want to make sure, that the lenght of the key
267
 * is somehow limited. When saving client sessions, the hostname is used
268
 * as key. According to HP-UX 10.20, MAXHOSTNAMELEN=64. Maybe new standards
269
 * will increase this value, but as this will break compatiblity with existing
270
 * implementations, we won't see this for long. We therefore choose a limit
271
 * of 64 bytes.
272
 * The length of the (TLS) session id can be up to 32 bytes according to
273
 * RFC2246, so it fits well into the 64bytes limit.
274
 */
275
#define ID_MAXLENGTH	64		/* Max ID length in bytes */
276
277
/*
278
 * The session_id_context is set, such that the client knows which services
279
 * on a host share the same session information (on the postfix host may
280
 * as well run a TLS-enabled webserver.
281
 */
282
static char server_session_id_context[] = "Postfix/TLS"; /* anything will do */
283
static int TLScontext_index = -1;
284
static int TLSpeername_index = -1;
285
static int do_dump = 0;
286
static DH *dh_512 = NULL, *dh_1024 = NULL;
287
static SSL_CTX *ctx = NULL;
288
289
static int rand_exch_fd = -1;
290
291
static DICT *scache_db = NULL;
292
const long scache_db_version = 0x00000003L;
293
const long openssl_version = OPENSSL_VERSION_NUMBER;
294
295
296
int     pfixtls_serverengine = 0;
297
static int pfixtls_serveractive = 0;	/* available or not */
298
299
int     pfixtls_clientengine = 0;
300
static int pfixtls_clientactive = 0;	/* available or not */
301
302
/*
303
 * Define a maxlength for certificate onelines. The length is checked by
304
 * all routines when copying.
305
 */
306
#define CCERT_BUFSIZ 256
307
308
typedef struct {
309
  SSL *con;
310
  BIO *internal_bio;			/* postfix/TLS side of pair */
311
  BIO *network_bio;			/* netsork side of pair */
312
  char peer_subject[CCERT_BUFSIZ];
313
  char peer_issuer[CCERT_BUFSIZ];
314
  char peer_CN[CCERT_BUFSIZ];
315
  char issuer_CN[CCERT_BUFSIZ];
316
  unsigned char md[EVP_MAX_MD_SIZE];
317
  char fingerprint[EVP_MAX_MD_SIZE * 3];
318
  char peername_save[129];
319
  int enforce_verify_errors;
320
  int enforce_CN;
321
} TLScontext_t;
322
323
typedef struct {
324
    int pid;
325
    struct timeval tv;
326
} randseed_t;
327
328
static randseed_t randseed;
329
330
/*
331
 * Finally some "backup" DH-Parameters to be loaded, if no parameters are
332
 * explicitely loaded from file.
333
 */
334
static unsigned char dh512_p[] = {
335
    0x88, 0x3F, 0x00, 0xAF, 0xFC, 0x0C, 0x8A, 0xB8, 0x35, 0xCD, 0xE5, 0xC2,
336
    0x0F, 0x55, 0xDF, 0x06, 0x3F, 0x16, 0x07, 0xBF, 0xCE, 0x13, 0x35, 0xE4,
337
    0x1C, 0x1E, 0x03, 0xF3, 0xAB, 0x17, 0xF6, 0x63, 0x50, 0x63, 0x67, 0x3E,
338
    0x10, 0xD7, 0x3E, 0xB4, 0xEB, 0x46, 0x8C, 0x40, 0x50, 0xE6, 0x91, 0xA5,
339
    0x6E, 0x01, 0x45, 0xDE, 0xC9, 0xB1, 0x1F, 0x64, 0x54, 0xFA, 0xD9, 0xAB,
340
    0x4F, 0x70, 0xBA, 0x5B,
341
};
342
343
static unsigned char dh512_g[] = {
344
    0x02,
345
};
346
347
static unsigned char dh1024_p[] = {
348
    0xB0, 0xFE, 0xB4, 0xCF, 0xD4, 0x55, 0x07, 0xE7, 0xCC, 0x88, 0x59, 0x0D,
349
    0x17, 0x26, 0xC5, 0x0C, 0xA5, 0x4A, 0x92, 0x23, 0x81, 0x78, 0xDA, 0x88,
350
    0xAA, 0x4C, 0x13, 0x06, 0xBF, 0x5D, 0x2F, 0x9E, 0xBC, 0x96, 0xB8, 0x51,
351
    0x00, 0x9D, 0x0C, 0x0D, 0x75, 0xAD, 0xFD, 0x3B, 0xB1, 0x7E, 0x71, 0x4F,
352
    0x3F, 0x91, 0x54, 0x14, 0x44, 0xB8, 0x30, 0x25, 0x1C, 0xEB, 0xDF, 0x72,
353
    0x9C, 0x4C, 0xF1, 0x89, 0x0D, 0x68, 0x3F, 0x94, 0x8E, 0xA4, 0xFB, 0x76,
354
    0x89, 0x18, 0xB2, 0x91, 0x16, 0x90, 0x01, 0x99, 0x66, 0x8C, 0x53, 0x81,
355
    0x4E, 0x27, 0x3D, 0x99, 0xE7, 0x5A, 0x7A, 0xAF, 0xD5, 0xEC, 0xE2, 0x7E,
356
    0xFA, 0xED, 0x01, 0x18, 0xC2, 0x78, 0x25, 0x59, 0x06, 0x5C, 0x39, 0xF6,
357
    0xCD, 0x49, 0x54, 0xAF, 0xC1, 0xB1, 0xEA, 0x4A, 0xF9, 0x53, 0xD0, 0xDF,
358
    0x6D, 0xAF, 0xD4, 0x93, 0xE7, 0xBA, 0xAE, 0x9B,
359
};
360
361
static unsigned char dh1024_g[] = {
362
    0x02,
363
};
364
365
/*
366
 * DESCRIPTION: Keeping control of the network interface using BIO-pairs.
367
 *
368
 * When the TLS layer is active, all input/output must be filtered through
369
 * it. On the other hand to handle timeout conditions, full control over
370
 * the network socket must be kept. This rules out the "normal way" of
371
 * connecting the TLS layer directly to the socket.
372
 * The TLS layer is realized with a BIO-pair:
373
 *
374
 *     postfix  |   TLS-engine
375
 *       |      |
376
 *       +--------> SSL_operations()
377
 *              |     /\    ||
378
 *              |     ||    \/
379
 *              |   BIO-pair (internal_bio)
380
 *       +--------< BIO-pair (network_bio)
381
 *       |      |
382
 *     socket   |
383
 *
384
 * The normal postfix operations connect to the SSL operations to send
385
 * and retrieve (cleartext) data. Inside the TLS-engine the data are converted
386
 * to/from TLS protocol. The TLS functionality itself is only connected to
387
 * the internal_bio and hence only has status information about this internal
388
 * interface.
389
 * Thus, if the SSL_operations() return successfully (SSL_ERROR_NONE) or want
390
 * to read (SSL_ERROR_WANT_READ) there may as well be data inside the buffering
391
 * BIO-pair. So whenever an SSL_operation() returns without a fatal error,
392
 * the BIO-pair internal buffer must be flushed to the network.
393
 * NOTE: This is especially true in the SSL_ERROR_WANT_READ case: the TLS-layer
394
 * might want to read handshake data, that will never come since its own
395
 * written data will only reach the peer after flushing the buffer!
396
 *
397
 * The BIO-pair buffer size has been set to 8192 bytes, this is an arbitrary
398
 * value that can hold more data than the typical PMTU, so that it does
399
 * not force the generation of packets smaller than necessary.
400
 * It is also larger than the default VSTREAM_BUFSIZE (4096, see vstream.h),
401
 * so that large write operations could be handled within one call.
402
 * The internal buffer in the network/network_bio handling layer has been
403
 * set to the same value, since this seems to be reasonable. The code is
404
 * however able to handle arbitrary values smaller or larger than the
405
 * buffer size in the BIO-pair.
406
 */
407
408
const ssize_t BIO_bufsiz = 8192;
409
410
/*
411
 * The interface layer between network and BIO-pair. The BIO-pair buffers
412
 * the data to/from the TLS layer. Hence, at any time, there may be data
413
 * in the buffer that must be written to the network. This writing has
414
 * highest priority because the handshake might fail otherwise.
415
 * Only then a read_request can be satisfied.
416
 */
417
static int network_biopair_interop(int fd, int timeout, BIO *network_bio)
418
{
419
    int want_write;
420
    int num_write;
421
    int write_pos;
422
    int from_bio;
423
    int want_read;
424
    int num_read;
425
    int to_bio;
426
#define NETLAYER_BUFFERSIZE 8192
427
    char buffer[8192];
428
429
    while ((want_write = BIO_ctrl_pending(network_bio)) > 0) {
430
	if (want_write > NETLAYER_BUFFERSIZE)
431
	    want_write = NETLAYER_BUFFERSIZE;
432
	from_bio = BIO_read(network_bio, buffer, want_write);
433
434
	/*
435
	 * Write the complete contents of the buffer. Since TLS performs
436
	 * underlying handshaking, we cannot afford to leave the buffer
437
	 * unflushed, as we could run into a deadlock trap (the peer
438
	 * waiting for a final byte and we already waiting for his reply
439
	 * in read position).
440
	 */
441
        write_pos = 0;
442
	do {
443
	    if (timeout > 0 && write_wait(fd, timeout) < 0)
444
		return (-1);
445
	    num_write = write(fd, buffer + write_pos, from_bio - write_pos);
446
	    if (num_write <= 0)
447
		return (-1);	/* something happened to the socket */
448
	    write_pos += num_write;
449
	} while (write_pos < from_bio);
450
   }
451
452
   while ((want_read = BIO_ctrl_get_read_request(network_bio)) > 0) {
453
	if (want_read > NETLAYER_BUFFERSIZE)
454
	    want_read = NETLAYER_BUFFERSIZE;
455
	if (timeout > 0 && read_wait(fd, timeout) < 0)
456
	    return (-1);
457
	num_read = read(fd, buffer, want_read);
458
	if (num_read <= 0)
459
	    return (-1);	/* something happened to the socket */
460
	to_bio = BIO_write(network_bio, buffer, num_read);
461
	if (to_bio != num_read)
462
		msg_fatal("to_bio != num_read");
463
    }
464
465
    return (0);
466
}
467
468
static void pfixtls_print_errors(void);
469
470
 /*
471
  * Function to perform the handshake for SSL_accept(), SSL_connect(),
472
  * and SSL_shutdown() and perform the SSL_read(), SSL_write() operations.
473
  * Call the underlying network_biopair_interop-layer to make sure the
474
  * write buffer is flushed after every operation (that did not fail with
475
  * a fatal error).
476
  */
477
static int do_tls_operation(int fd, int timeout, TLScontext_t *TLScontext,
478
			int (*hsfunc)(SSL *),
479
			int (*rfunc)(SSL *, void *, int),
480
			int (*wfunc)(SSL *, const void *, int),
481
			char *buf, int num)
482
{
483
    int status;
484
    int err;
485
    int retval = 0;
486
    int biop_retval;
487
    int done = 0;
488
489
    while (!done) {
490
	if (hsfunc)
491
	    status = hsfunc(TLScontext->con);
492
	else if (rfunc)
493
	    status = rfunc(TLScontext->con, buf, num);
494
	else
495
	    status = wfunc(TLScontext->con, (const char *)buf, num);
496
	err = SSL_get_error(TLScontext->con, status);
497
498
#if (OPENSSL_VERSION_NUMBER <= 0x0090581fL)
499
	/*
500
	 * There is a bug up to and including OpenSSL-0.9.5a: if an error
501
	 * occurs while checking the peers certificate due to some certificate
502
	 * error (e.g. as happend with a RSA-padding error), the error is put
503
	 * onto the error stack. If verification is not enforced, this error
504
	 * should be ignored, but the error-queue is not cleared, so we
505
	 * can find this error here. The bug has been fixed on May 28, 2000.
506
	 *
507
	 * This bug so far has only manifested as
508
	 * 4800:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:rsa_pk1.c:100:
509
	 * 4800:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed:rsa_eay.c:396:
510
	 * 4800:error:0D079006:asn1 encoding routines:ASN1_verify:bad get asn1 object call:a_verify.c:109:
511
	 * so that we specifically test for this error. We print the errors
512
	 * to the logfile and automatically clear the error queue. Then we
513
	 * retry to get another error code. We cannot do better, since we
514
	 * can only retrieve the last entry of the error-queue without
515
	 * actually cleaning it on the way.
516
	 *
517
	 * This workaround is secure, as verify_result is set to "failed"
518
	 * anyway.
519
	 */
520
	if (err == SSL_ERROR_SSL) {
521
	    if (ERR_peek_error() == 0x0407006AL) {
522
		pfixtls_print_errors();	/* Keep information for the logfile */
523
		msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored");
524
		err = SSL_get_error(TLScontext->con, status);
525
	    }
526
	}
527
#endif
528
529
	switch (err) {
530
	case SSL_ERROR_NONE:		/* success */
531
	    retval = status;
532
	    done = 1;			/* no break, flush buffer before */
533
					/* leaving */
534
	case SSL_ERROR_WANT_WRITE:
535
	case SSL_ERROR_WANT_READ:
536
	    biop_retval = network_biopair_interop(fd, timeout,
537
		TLScontext->network_bio);
538
	    if (biop_retval < 0)
539
		return (-1);		/* fatal network error */
540
	    break;
541
	case SSL_ERROR_ZERO_RETURN:	/* connection was closed cleanly */
542
	case SSL_ERROR_SYSCALL:		
543
	case SSL_ERROR_SSL:
544
	default:
545
	    retval = status;
546
	    done = 1;
547
	    ;
548
	}
549
    };
550
    return retval;
551
}
552
553
int pfixtls_timed_read(int fd, void *buf, unsigned buf_len, int timeout, 
554
		       void *context)
555
{
556
    int     i;
557
    int     ret;
558
    char    mybuf[40];
559
    char   *mybuf2;
560
    TLScontext_t *TLScontext;
561
562
    TLScontext = (TLScontext_t *)context;
563
    if (!TLScontext)
564
      msg_fatal("Called tls_timed_read() without TLS-context");
565
 
566
    ret = do_tls_operation(fd, timeout, TLScontext, NULL, SSL_read, NULL,
567
			  (char *)buf, buf_len);
568
    if ((pfixtls_serveractive && var_smtpd_tls_loglevel >= 4) ||
569
        (pfixtls_clientactive && var_smtp_tls_loglevel >= 4)) {
570
	mybuf2 = (char *) buf;
571
	if (ret > 0) {
572
	    i = 0;
573
	    while ((i < 39) && (i < ret) && (mybuf2[i] != 0)) {
574
		mybuf[i] = mybuf2[i];
575
		i++;
576
	    }
577
	    mybuf[i] = '\0';
578
	    msg_info("Read %d chars: %s", ret, mybuf);
579
	}
580
    }
581
    return (ret);
582
}
583
584
int pfixtls_timed_write(int fd, void *buf, unsigned len, int timeout,
585
			void *context)
586
{
587
    int     i;
588
    char    mybuf[40];
589
    char   *mybuf2;
590
    TLScontext_t *TLScontext;
591
592
    TLScontext = (TLScontext_t *)context;
593
    if (!TLScontext)
594
      msg_fatal("Called tls_timed_write() without TLS-context");
595
596
    if ((pfixtls_serveractive && var_smtpd_tls_loglevel >= 4) ||
597
	(pfixtls_clientactive && var_smtp_tls_loglevel >= 4)) {
598
	mybuf2 = (char *) buf;
599
	if (len > 0) {
600
	    i = 0;
601
	    while ((i < 39) && (i < len) && (mybuf2[i] != 0)) {
602
		mybuf[i] = mybuf2[i];
603
		i++;
604
	    }
605
	    mybuf[i] = '\0';
606
	    msg_info("Write %d chars: %s", len, mybuf);
607
	}
608
    }
609
    return (do_tls_operation(fd, timeout, TLScontext, NULL, NULL, SSL_write,
610
			     buf, len));
611
}
612
613
/* Add some more entropy to the pool by adding the actual time */
614
615
static void pfixtls_stir_seed(void)
616
{
617
    GETTIMEOFDAY(&randseed.tv);
618
    RAND_seed(&randseed, sizeof(randseed_t));
619
}
620
621
/*
622
 * Skeleton taken from OpenSSL crypto/err/err_prn.c.
623
 * Query the error stack and print the error string into the logging facility.
624
 * Clear the error stack on the way.
625
 */
626
627
static void pfixtls_print_errors(void)
628
{
629
    unsigned long l;
630
    char    buf[256];
631
    const char   *file;
632
    const char   *data;
633
    int     line;
634
    int     flags;
635
    unsigned long es;
636
637
    es = CRYPTO_thread_id();
638
    while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
639
	if (flags & ERR_TXT_STRING)
640
	    msg_info("%lu:%s:%s:%d:%s:", es, ERR_error_string(l, buf),
641
		     file, line, data);
642
	else
643
	    msg_info("%lu:%s:%s:%d:", es, ERR_error_string(l, buf),
644
		     file, line);
645
    }
646
}
647
648
 /*
649
  * Set up the cert things on the server side. We do need both the
650
  * private key (in key_file) and the cert (in cert_file).
651
  * Both files may be identical.
652
  *
653
  * This function is taken from OpenSSL apps/s_cb.c
654
  */
655
656
static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
657
{
658
    if (cert_file != NULL) {
659
	if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
660
	    msg_info("unable to get certificate from '%s'", cert_file);
661
	    pfixtls_print_errors();
662
	    return (0);
663
	}
664
	if (key_file == NULL)
665
	    key_file = cert_file;
666
	if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
667
					SSL_FILETYPE_PEM) <= 0) {
668
	    msg_info("unable to get private key from '%s'", key_file);
669
	    pfixtls_print_errors();
670
	    return (0);
671
	}
672
	/* Now we know that a key and cert have been set against
673
         * the SSL context */
674
	if (!SSL_CTX_check_private_key(ctx)) {
675
	    msg_info("Private key does not match the certificate public key");
676
	    return (0);
677
	}
678
    }
679
    return (1);
680
}
681
682
/* taken from OpenSSL apps/s_cb.c */
683
684
static RSA *tmp_rsa_cb(SSL * s, int export, int keylength)
685
{
686
    static RSA *rsa_tmp = NULL;
687
688
    if (rsa_tmp == NULL) {
689
	rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
690
    }
691
    return (rsa_tmp);
692
}
693
694
695
static DH *get_dh512(void)
696
{
697
    DH *dh;
698
699
    if (dh_512 == NULL) {
700
	/* No parameter file loaded, use the compiled in parameters */
701
	if ((dh = DH_new()) == NULL) return(NULL);
702
	dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
703
	dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
704
	if ((dh->p == NULL) || (dh->g == NULL))
705
	    return(NULL);
706
	else
707
	    dh_512 = dh;
708
    }
709
    return (dh_512);
710
}
711
712
static DH *get_dh1024(void)
713
{
714
    DH *dh;
715
716
    if (dh_1024 == NULL) {
717
	/* No parameter file loaded, use the compiled in parameters */
718
	if ((dh = DH_new()) == NULL) return(NULL);
719
	dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
720
	dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
721
	if ((dh->p == NULL) || (dh->g == NULL))
722
	    return(NULL);
723
	else
724
	    dh_1024 = dh;
725
    }
726
    return (dh_1024);
727
}
728
729
/* partly inspired by mod_ssl */
730
731
static DH *tmp_dh_cb(SSL *s, int export, int keylength)
732
{
733
    DH *dh_tmp = NULL;
734
   
735
    if (export) {
736
	if (keylength == 512)
737
	    dh_tmp = get_dh512();	/* export cipher */
738
	else if (keylength == 1024)
739
	    dh_tmp = get_dh1024();	/* normal */
740
	else
741
	    dh_tmp = get_dh1024();	/* not on-the-fly (too expensive) */
742
					/* so use the 1024bit instead */
743
    }
744
    else {
745
	dh_tmp = get_dh1024();		/* sign-only certificate */
746
    }
747
    return (dh_tmp);
748
}
749
750
751
/*
752
 * Skeleton taken from OpenSSL apps/s_cb.c
753
 *
754
 * The verify_callback is called several times (directly or indirectly) from
755
 * crypto/x509/x509_vfy.c. It is called as a last check for several issues,
756
 * so this verify_callback() has the famous "last word". If it does return "0",
757
 * the handshake is immediately shut down and the connection fails.
758
 *
759
 * Postfix/TLS has two modes, the "use" mode and the "enforce" mode:
760
 *
761
 * In the "use" mode we never want the connection to fail just because there is
762
 * something wrong with the certificate (as we would have sent happily without
763
 * TLS).  Therefore the return value is always "1".
764
 *
765
 * In the "enforce" mode we can shut down the connection as soon as possible.
766
 * In server mode TLS itself may be enforced (e.g. to protect passwords),
767
 * but certificates are optional. In this case the handshake must not fail
768
 * if we are unhappy with the certificate and return "1" in any case.
769
 * Only if a certificate is required the certificate must pass the verification
770
 * and failure to do so will result in immediate termination (return 0).
771
 * In the client mode the decision is made with respect to the peername
772
 * enforcement. If we strictly enforce the matching of the expected peername
773
 * the verification must fail immediatly on verification errors. We can also
774
 * immediatly check the expected peername, as it is the CommonName at level 0.
775
 * In all other cases, the problem is logged, so the SSL_get_verify_result()
776
 * will inform about the verification failure, but the handshake (and SMTP
777
 * connection will continue).
778
 *
779
 * The only error condition not handled inside the OpenSSL-Library is the
780
 * case of a too-long certificate chain, so we check inside verify_callback().
781
 * We only take care of this problem, if "ok = 1", because otherwise the
782
 * verification already failed because of another problem and we don't want
783
 * to overwrite the other error message. And if the verification failed,
784
 * there is no such thing as "more failed", "most failed"... :-)
785
 */
786
787
static int verify_callback(int ok, X509_STORE_CTX * ctx)
788
{
789
    char    buf[256];
790
    char   *CN_lowercase;
791
    char   *peername_left;
792
    X509   *err_cert;
793
    int     err;
794
    int     depth;
795
    int     verify_depth;
796
    int     hostname_matched;
797
    SSL    *con;
798
    TLScontext_t *TLScontext;
799
800
    err_cert = X509_STORE_CTX_get_current_cert(ctx);
801
    err = X509_STORE_CTX_get_error(ctx);
802
    depth = X509_STORE_CTX_get_error_depth(ctx);
803
804
    con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
805
    TLScontext = SSL_get_ex_data(con, TLScontext_index);
806
807
    X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
808
    if (((pfixtls_serverengine) && (var_smtpd_tls_loglevel >= 2)) ||
809
	((pfixtls_clientengine) && (var_smtp_tls_loglevel >= 2)))
810
	msg_info("Peer cert verify depth=%d %s", depth, buf);
811
812
    verify_depth = SSL_get_verify_depth(con);
813
    if (ok && (verify_depth >= 0) && (depth > verify_depth)) {
814
	ok = 0;
815
	err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
816
	X509_STORE_CTX_set_error(ctx, err);
817
    }
818
    if (!ok) {
819
	msg_info("verify error:num=%d:%s", err,
820
		 X509_verify_cert_error_string(err));
821
    }
822
823
    if (ok && (depth == 0) && pfixtls_clientengine) {
824
	/*
825
	 * Check out the name certified against the hostname expected.
826
	 * In case it does not match, print an information about the result.
827
	 * If a matching is enforced, bump out with a verification error
828
	 * immediately.
829
	 */
830
	buf[0] = '\0';
831
	if (!X509_NAME_get_text_by_NID(X509_get_subject_name(err_cert),
832
                          NID_commonName, buf, 256)) {
833
	    msg_info("Could not parse server's subject CN");
834
	    pfixtls_print_errors();
835
	}
836
	CN_lowercase = lowercase(buf);
837
	hostname_matched = 0;
838
	if (!strcmp(TLScontext->peername_save, CN_lowercase))
839
	    hostname_matched = 1;
840
	else if ((strlen(CN_lowercase) > 2) &&
841
		 (CN_lowercase[0] == '*') && (CN_lowercase[1] == '.')) {
842
	    /*
843
	     * Allow wildcard certificate matching. The proposed rules in
844
	     * RFCs (2818: HTTP/TLS, 2830: LDAP/TLS) are different, RFC2874
845
	     * does not specify a rule, so here the strict rule is applied.
846
	     * An asterisk '*' is allowed as the leftmost component and may
847
	     * replace the left most part of the hostname. Matching is done
848
	     * by removing '*.' from the wildcard name and the `name.` from
849
	     * the peername and compare what is left.
850
	     */
851
	    peername_left = strchr(TLScontext->peername_save, '.');
852
	    if (peername_left) {
853
		if (!strcmp(peername_left + 1, CN_lowercase + 2))
854
		    hostname_matched = 1;
855
	    }
856
	}
857
858
	if (!hostname_matched) {
859
		msg_info("Peer verification: CommonName in certificate does not match: %s != %s", CN_lowercase, TLScontext->peername_save);
860
	    if (TLScontext->enforce_verify_errors && TLScontext->enforce_CN) {
861
		err = X509_V_ERR_CERT_REJECTED;
862
		X509_STORE_CTX_set_error(ctx, err);
863
		msg_info("Verify failure: Hostname mismatch");
864
		ok = 0;
865
	    }
866
	}
867
    }
868
869
    switch (ctx->error) {
870
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
871
	X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
872
	msg_info("issuer= %s", buf);
873
	break;
874
    case X509_V_ERR_CERT_NOT_YET_VALID:
875
    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
876
	msg_info("cert not yet valid");
877
	break;
878
    case X509_V_ERR_CERT_HAS_EXPIRED:
879
    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
880
	msg_info("cert has expired");
881
	break;
882
    }
883
    if (((pfixtls_serverengine) && (var_smtpd_tls_loglevel >= 2)) ||
884
	((pfixtls_clientengine) && (var_smtp_tls_loglevel >= 2)))
885
	msg_info("verify return:%d", ok);
886
887
    if (TLScontext->enforce_verify_errors)
888
	return (ok); 
889
    else
890
	return (1);
891
}
892
893
/* taken from OpenSSL apps/s_cb.c */
894
895
static void apps_ssl_info_callback(SSL * s, int where, int ret)
896
{
897
    char   *str;
898
    int     w;
899
900
    w = where & ~SSL_ST_MASK;
901
902
    if (w & SSL_ST_CONNECT)
903
	str = "SSL_connect";
904
    else if (w & SSL_ST_ACCEPT)
905
	str = "SSL_accept";
906
    else
907
	str = "undefined";
908
909
    if (where & SSL_CB_LOOP) {
910
	    msg_info("%s:%s", str, SSL_state_string_long(s));
911
    } else if (where & SSL_CB_ALERT) {
912
	str = (where & SSL_CB_READ) ? "read" : "write";
913
	if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
914
	msg_info("SSL3 alert %s:%s:%s", str,
915
		 SSL_alert_type_string_long(ret),
916
		 SSL_alert_desc_string_long(ret));
917
    } else if (where & SSL_CB_EXIT) {
918
	if (ret == 0)
919
	    msg_info("%s:failed in %s",
920
		     str, SSL_state_string_long(s));
921
	else if (ret < 0) {
922
	    msg_info("%s:error in %s",
923
		     str, SSL_state_string_long(s));
924
	}
925
    }
926
}
927
928
/*
929
 * taken from OpenSSL crypto/bio/b_dump.c, modified to save a lot of strcpy
930
 * and strcat by Matti Aarnio.
931
 */
932
933
#define TRUNCATE
934
#define DUMP_WIDTH	16
935
936
static int pfixtls_dump(const char *s, int len)
937
{
938
    int     ret = 0;
939
    char    buf[160 + 1];
940
    char    *ss;
941
    int     i;
942
    int     j;
943
    int     rows;
944
    int     trunc;
945
    unsigned char ch;
946
947
    trunc = 0;
948
949
#ifdef TRUNCATE
950
    for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--)
951
	trunc++;
952
#endif
953
954
    rows = (len / DUMP_WIDTH);
955
    if ((rows * DUMP_WIDTH) < len)
956
	rows++;
957
958
    for (i = 0; i < rows; i++) {
959
	buf[0] = '\0';				/* start with empty string */
960
	ss = buf;
961
962
	sprintf(ss, "%04x ", i * DUMP_WIDTH);
963
	ss += strlen(ss);
964
	for (j = 0; j < DUMP_WIDTH; j++) {
965
	    if (((i * DUMP_WIDTH) + j) >= len) {
966
		strcpy(ss, "   ");
967
	    } else {
968
		ch = ((unsigned char) *((char *) (s) + i * DUMP_WIDTH + j))
969
		    & 0xff;
970
		sprintf(ss, "%02x%c", ch, j == 7 ? '|' : ' ');
971
		ss += 3;
972
	    }
973
	}
974
	ss += strlen(ss);
975
	*ss++ = ' ';
976
	for (j = 0; j < DUMP_WIDTH; j++) {
977
	    if (((i * DUMP_WIDTH) + j) >= len)
978
		break;
979
	    ch = ((unsigned char) *((char *) (s) + i * DUMP_WIDTH + j)) & 0xff;
980
	    *ss++ = (((ch >= ' ') && (ch <= '~')) ? ch : '.');
981
	    if (j == 7) *ss++ = ' ';
982
	}
983
	*ss = 0;
984
	/* 
985
	 * if this is the last call then update the ddt_dump thing so that
986
         * we will move the selection point in the debug window
987
         */
988
	msg_info("%s", buf);
989
	ret += strlen(buf);
990
    }
991
#ifdef TRUNCATE
992
    if (trunc > 0) {
993
	sprintf(buf, "%04x - <SPACES/NULS>\n", len + trunc);
994
	msg_info("%s", buf);
995
	ret += strlen(buf);
996
    }
997
#endif
998
    return (ret);
999
}
1000
1001
1002
1003
/* taken from OpenSSL apps/s_cb.c */
1004
1005
static long bio_dump_cb(BIO * bio, int cmd, const char *argp, int argi,
1006
			long argl, long ret)
1007
{
1008
    if (!do_dump)
1009
	return (ret);
1010
1011
    if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
1012
	msg_info("read from %08X [%08lX] (%d bytes => %ld (0x%X))",
1013
		 (unsigned int)bio, (unsigned long)argp, argi,
1014
		 ret, (unsigned int)ret);
1015
	pfixtls_dump(argp, (int) ret);
1016
	return (ret);
1017
    } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
1018
	msg_info("write to %08X [%08lX] (%d bytes => %ld (0x%X))",
1019
		 (unsigned int)bio, (unsigned long)argp, argi,
1020
	 	 ret, (unsigned int)ret);
1021
	pfixtls_dump(argp, (int) ret);
1022
    }
1023
    return (ret);
1024
}
1025
1026
1027
 /*
1028
  * Callback to retrieve a session from the external session cache.
1029
  */
1030
static SSL_SESSION *get_session_cb(SSL *ssl, unsigned char *SessionID,
1031
				  int length, int *copy)
1032
{
1033
    SSL_SESSION *session;
1034
    char idstring[2 * ID_MAXLENGTH + 1];
1035
    int n;
1036
    int uselength;
1037
    int hex_length;
1038
    const char *session_hex;
1039
    pfixtls_scache_info_t scache_info;
1040
    unsigned char nibble, *data, *sess_data;
1041
1042
    if (length > ID_MAXLENGTH)
1043
	uselength = ID_MAXLENGTH;	/* Limit length of ID */
1044
    else
1045
	uselength = length;
1046
1047
    for(n=0 ; n < uselength ; n++)
1048
	sprintf(idstring + 2 * n, "%02x", SessionID[n]);
1049
    if (var_smtpd_tls_loglevel >= 3)
1050
	msg_info("Trying to reload Session from disc: %s", idstring);
1051
1052
    session = NULL;
1053
1054
    session_hex = dict_get(scache_db, idstring);
1055
    if (session_hex) {
1056
	hex_length = strlen(session_hex);
1057
	data = (unsigned char *)mymalloc(hex_length / 2);
1058
	if (!data) {
1059
	    msg_info("could not allocate memory for session reload");
1060
	    return(NULL);
1061
	}
1062
1063
	memset(data, 0, hex_length / 2);
1064
	for (n = 0; n < hex_length; n++) {
1065
	    if ((session_hex[n] >= '0') && (session_hex[n] <= '9'))
1066
		nibble = session_hex[n] - '0';
1067
	    else
1068
		nibble = session_hex[n] - 'A' + 10;
1069
	    if (n % 2)
1070
		data[n / 2] |= nibble;
1071
	    else
1072
		data[n / 2] |= (nibble << 4);
1073
	}
1074
1075
	/*
1076
	 * First check the version numbers, since wrong session data might
1077
	 * hit us hard (SEGFAULT). We also have to check for expiry.
1078
	 */
1079
	memcpy(&scache_info, data, sizeof(pfixtls_scache_info_t));
1080
	if ((scache_info.scache_db_version != scache_db_version) ||
1081
	    (scache_info.openssl_version != openssl_version) ||
1082
	    (scache_info.timestamp + var_smtpd_tls_scache_timeout < time(NULL)))
1083
	    dict_del(scache_db, idstring);
1084
	else {
1085
	    sess_data = data + sizeof(pfixtls_scache_info_t);
1086
	    session = d2i_SSL_SESSION(NULL, &sess_data,
1087
			      hex_length / 2 - sizeof(pfixtls_scache_info_t));
1088
	    if (!session)
1089
		pfixtls_print_errors();
1090
	}
1091
	myfree((char *)data);
1092
    }
1093
1094
    if (session && (var_smtpd_tls_loglevel >= 3))
1095
	msg_info("Successfully reloaded session from disc");
1096
1097
    return (session);
1098
}
1099
1100
1101
static SSL_SESSION *load_clnt_session(const char *hostname,
1102
				      int enforce_peername)
1103
{
1104
    SSL_SESSION *session = NULL;
1105
    char idstring[ID_MAXLENGTH + 1];
1106
    int n;
1107
    int uselength;
1108
    int length;
1109
    int hex_length;
1110
    const char *session_hex;
1111
    pfixtls_scache_info_t scache_info;
1112
    unsigned char nibble, *data, *sess_data;
1113
1114
    length = strlen(hostname); 
1115
    if (length > ID_MAXLENGTH)
1116
	uselength = ID_MAXLENGTH;	/* Limit length of ID */
1117
    else
1118
	uselength = length;
1119
1120
    for(n=0 ; n < uselength ; n++)
1121
	idstring[n] = tolower(hostname[n]);
1122
    idstring[uselength] = '\0';
1123
    if (var_smtp_tls_loglevel >= 3)
1124
	msg_info("Trying to reload Session from disc: %s", idstring);
1125
1126
    session_hex = dict_get(scache_db, idstring);
1127
    if (session_hex) {
1128
	hex_length = strlen(session_hex);
1129
	data = (unsigned char *)mymalloc(hex_length / 2);
1130
	if (!data) {
1131
	    msg_info("could not allocate memory for session reload");
1132
	    return(NULL);
1133
	}
1134
1135
	memset(data, 0, hex_length / 2);
1136
	for (n = 0; n < hex_length; n++) {
1137
	    if ((session_hex[n] >= '0') && (session_hex[n] <= '9'))
1138
		nibble = session_hex[n] - '0';
1139
	    else
1140
		nibble = session_hex[n] - 'A' + 10;
1141
	    if (n % 2)
1142
		data[n / 2] |= nibble;
1143
	    else
1144
		data[n / 2] |= (nibble << 4);
1145
	}
1146
1147
	/*
1148
	 * First check the version numbers, since wrong session data might
1149
	 * hit us hard (SEGFAULT). We also have to check for expiry.
1150
	 * When we enforce_peername, we may find an old session, that was
1151
	 * saved when enforcement was not set. In this case the session will
1152
	 * be removed and a fresh session will be negotiated.
1153
	 */
1154
	memcpy(&scache_info, data, sizeof(pfixtls_scache_info_t));
1155
	if ((scache_info.scache_db_version != scache_db_version) ||
1156
	    (scache_info.openssl_version != openssl_version) ||
1157
	    (scache_info.timestamp + var_smtpd_tls_scache_timeout < time(NULL)))
1158
	    dict_del(scache_db, idstring);
1159
	else if (enforce_peername && (!scache_info.enforce_peername))
1160
	    dict_del(scache_db, idstring);
1161
	else {
1162
	    sess_data = data + sizeof(pfixtls_scache_info_t);
1163
	    session = d2i_SSL_SESSION(NULL, &sess_data,
1164
				      hex_length / 2 - sizeof(time_t));
1165
	    strncpy(SSL_SESSION_get_ex_data(session, TLSpeername_index),
1166
		    idstring, ID_MAXLENGTH + 1);
1167
	    if (!session)
1168
		pfixtls_print_errors();
1169
	}
1170
	myfree((char *)data);
1171
    }
1172
1173
    if (session && (var_smtp_tls_loglevel >= 3))
1174
        msg_info("Successfully reloaded session from disc");
1175
1176
    return (session);
1177
}
1178
1179
1180
static void create_client_lookup_id(char *idstring, char *hostname)
1181
{
1182
    int n, len, uselength;
1183
1184
    len = strlen(hostname);
1185
    if (len > ID_MAXLENGTH)
1186
	uselength = ID_MAXLENGTH;	/* Limit length of ID */
1187
    else
1188
	uselength = len;
1189
1190
    for (n = 0 ; n < uselength ; n++)
1191
	idstring[n] = tolower(hostname[n]);
1192
    idstring[uselength] = '\0';
1193
}
1194
1195
1196
static void create_server_lookup_id(char *idstring, SSL_SESSION *session)
1197
{
1198
    int n, uselength;
1199
1200
    if (session->session_id_length > ID_MAXLENGTH)
1201
	uselength = ID_MAXLENGTH;	/* Limit length of ID */
1202
    else
1203
	uselength = session->session_id_length;
1204
1205
    for(n = 0; n < uselength ; n++)
1206
	sprintf(idstring + 2 * n, "%02x", session->session_id[n]);
1207
}
1208
1209
1210
static void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *session)
1211
{
1212
    char idstring[2 * ID_MAXLENGTH + 1];
1213
    char *hostname;
1214
1215
    if (pfixtls_clientengine) {
1216
        hostname = SSL_SESSION_get_ex_data(session, TLSpeername_index);
1217
	create_client_lookup_id(idstring, hostname);
1218
	if (var_smtp_tls_loglevel >= 3)
1219
	    msg_info("Trying to remove session from disc: %s", idstring);
1220
    }
1221
    else {
1222
	create_server_lookup_id(idstring, session);
1223
	if (var_smtpd_tls_loglevel >= 3)
1224
	    msg_info("Trying to remove session from disc: %s", idstring);
1225
    }
1226
1227
    if (scache_db)
1228
	dict_del(scache_db, idstring);
1229
}
1230
1231
1232
/*
1233
 * We need space to save the peername into the SSL_SESSION, as we must
1234
 * look up the external database for client sessions by peername, not
1235
 * by session id. We therefore allocate place for the peername string,
1236
 * when a new SSL_SESSION is generated. It is filled later.
1237
 */
1238
static int new_peername_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
1239
			     int idx, long argl, void *argp)
1240
{
1241
    char *peername;
1242
1243
    peername = (char *)mymalloc(ID_MAXLENGTH + 1);
1244
    if (!peername)
1245
	return 0;
1246
    peername[0] = '\0'; 	/* initialize */
1247
    return CRYPTO_set_ex_data(ad, idx, peername);
1248
}
1249
1250
/*
1251
 * When the SSL_SESSION is removed again, we must free the memory to avoid
1252
 * leaks.
1253
 */
1254
static void free_peername_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
1255
			       int idx, long argl, void *argp)
1256
{
1257
    myfree(CRYPTO_get_ex_data(ad, idx));
1258
}
1259
1260
/*
1261
 * Duplicate application data, when a SSL_SESSION is duplicated
1262
 */
1263
static int dup_peername_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from,
1264
			     void *from_d, int idx, long argl, void *argp)
1265
{
1266
    char *peername_old, *peername_new;
1267
1268
    peername_old = CRYPTO_get_ex_data(from, idx);
1269
    peername_new = CRYPTO_get_ex_data(to, idx);
1270
    if (!peername_old || !peername_new)
1271
	return 0;
1272
    memcpy(peername_new, peername_old, ID_MAXLENGTH + 1);
1273
    return 1;
1274
}
1275
1276
1277
 /*
1278
  * Save a new session to the external cache
1279
  */
1280
static int new_session_cb(SSL *ssl, SSL_SESSION *session)
1281
{
1282
    char idstring[2 * ID_MAXLENGTH + 1];
1283
    int n;
1284
    int dsize;
1285
    int len;
1286
    unsigned char *data, *sess_data;
1287
    pfixtls_scache_info_t scache_info;
1288
    char *hexdata, *hostname;
1289
    TLScontext_t *TLScontext;
1290
1291
    if (pfixtls_clientengine) {
1292
        TLScontext = SSL_get_ex_data(ssl, TLScontext_index);
1293
	hostname = TLScontext->peername_save;
1294
	create_client_lookup_id(idstring, hostname);
1295
	strncpy(SSL_SESSION_get_ex_data(session, TLSpeername_index),
1296
		hostname, ID_MAXLENGTH + 1);
1297
	/*
1298
	 * Remember, whether peername matching was enforced when the session
1299
	 * was created. If later enforce mode is enabled, we do not want to
1300
	 * reuse a session that was not sufficiently checked.
1301
	 */
1302
	scache_info.enforce_peername =
1303
		(TLScontext->enforce_verify_errors && TLScontext->enforce_CN);
1304
1305
	if (var_smtp_tls_loglevel >= 3)
1306
	    msg_info("Trying to save session for hostID to disc: %s", idstring);
1307
1308
#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)
1309
	    /*
1310
	     * Ugly Hack: OpenSSL before 0.9.6a does not store the verify
1311
	     * result in sessions for the client side.
1312
	     * We modify the session directly which is version specific,
1313
	     * but this bug is version specific, too.
1314
	     *
1315
	     * READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before
1316
	     * beta1 have this bug, it has been fixed during development
1317
	     * of 0.9.6a. The development version of 0.9.7 can have this
1318
	     * bug, too. It has been fixed on 2000/11/29.
1319
	     */
1320
	    session->verify_result = SSL_get_verify_result(TLScontext->con);
1321
#endif
1322
1323
    }
1324
    else {
1325
	create_server_lookup_id(idstring, session);
1326
	if (var_smtpd_tls_loglevel >= 3)
1327
	    msg_info("Trying to save Session to disc: %s", idstring);
1328
    }
1329
1330
1331
    /*
1332
     * Get the session and convert it into some "database" useable form.
1333
     * First, get the length of the session to allocate the memory.
1334
     */
1335
    dsize = i2d_SSL_SESSION(session, NULL);
1336
    if (dsize < 0) {
1337
	msg_info("Could not access session");
1338
	return 0;
1339
    }
1340
    data = (unsigned char *)mymalloc(dsize + sizeof(pfixtls_scache_info_t));
1341
    if (!data) {
1342
	msg_info("could not allocate memory for SSL session");
1343
	return 0;
1344
    }
1345
1346
    /*
1347
     * OpenSSL is not robust against wrong session data (might SEGFAULT),
1348
     * so we secure it against version ids (session cache structure as well
1349
     * as OpenSSL version).
1350
     */
1351
    scache_info.scache_db_version = scache_db_version;
1352
    scache_info.openssl_version = openssl_version;
1353
1354
    /*
1355
     * Put a timestamp, so that expiration can be checked without
1356
     * analyzing the session data itself. (We would need OpenSSL funtions,
1357
     * since the SSL_SESSION is a private structure.)
1358
     */
1359
    scache_info.timestamp = time(NULL);
1360
1361
    memcpy(data, &scache_info, sizeof(pfixtls_scache_info_t));
1362
    sess_data = data + sizeof(pfixtls_scache_info_t);
1363
1364
    /*
1365
     * Now, obtain the session. Unfortunately, it is binary and dict_update
1366
     * cannot handle binary data (it could contain '\0' in it) directly.
1367
     * To save memory we could use base64 encoding. To make handling easier,
1368
     * we simply use hex format.
1369
     */
1370
    len = i2d_SSL_SESSION(session, &sess_data);
1371
    len += sizeof(pfixtls_scache_info_t);
1372
1373
    hexdata = (char *)mymalloc(2 * len + 1);
1374
1375
    if (!hexdata) {
1376
	msg_info("could not allocate memory for SSL session (HEX)");
1377
	myfree((char *)data);
1378
	return 0;
1379
    }
1380
    for (n = 0; n < len; n++) {
1381
	hexdata[n * 2] = hexcodes[(data[n] & 0xf0) >> 4];
1382
	hexdata[(n * 2) + 1] = hexcodes[(data[n] & 0x0f)];
1383
    }
1384
    hexdata[len * 2] = '\0';
1385
1386
    /*
1387
     * The session id is a hex string, all uppercase. We are using SDBM as
1388
     * compiled into Postfix with 8kB maximum entry size, so we set a limit
1389
     * when caching. If the session is not cached, we have to renegotiate,
1390
     * not more, not less. For a real session, this limit should never be
1391
     * met
1392
     */
1393
    if (strlen(idstring) + strlen(hexdata) < 8000)
1394
      dict_put(scache_db, idstring, hexdata);
1395
1396
    myfree(hexdata);
1397
    myfree((char *)data);
1398
    return (1);
1399
}
1400
1401
1402
 /*
1403
  * pfixtls_exchange_seed: read bytes from the seed exchange-file (expect
1404
  * 1024 bytes)and immediately write back random bytes. Do so with EXCLUSIVE
1405
  * lock, so * that each process will find a completely different (and
1406
  * reseeded) file.
1407
  */
1408
static void pfixtls_exchange_seed(void)
1409
{
1410
    unsigned char buffer[1024];
1411
1412
    if (rand_exch_fd == -1)
1413
	return;
1414
1415
    if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
1416
        msg_info("Could not lock random exchange file: %s",
1417
                  strerror(errno));
1418
1419
    lseek(rand_exch_fd, 0, SEEK_SET);
1420
    if (read(rand_exch_fd, buffer, 1024) < 0)
1421
        msg_fatal("reading exchange file failed");
1422
    RAND_seed(buffer, 1024);
1423
1424
    RAND_bytes(buffer, 1024);
1425
    lseek(rand_exch_fd, 0, SEEK_SET);
1426
    if (write(rand_exch_fd, buffer, 1024) != 1024)
1427
        msg_fatal("Writing exchange file failed");
1428
1429
    if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
1430
        msg_fatal("Could not unlock random exchange file: %s",
1431
                  strerror(errno));
1432
}
1433
1434
 /*
1435
  * This is the setup routine for the SSL server. As smtpd might be called
1436
  * more than once, we only want to do the initialization one time.
1437
  *
1438
  * The skeleton of this function is taken from OpenSSL apps/s_server.c.
1439
  */
1440
1441
int     pfixtls_init_serverengine(int verifydepth, int askcert)
1442
{
1443
    int     off = 0;
1444
    int     verify_flags = SSL_VERIFY_NONE;
1445
    int     rand_bytes;
1446
    int     rand_source_dev_fd;
1447
    int     rand_source_socket_fd;
1448
    unsigned char buffer[255];
1449
    char   *CApath;
1450
    char   *CAfile;
1451
    char   *s_cert_file;
1452
    char   *s_key_file;
1453
    char   *s_dcert_file;
1454
    char   *s_dkey_file;
1455
    FILE   *paramfile;
1456
1457
    if (pfixtls_serverengine)
1458
	return (0);				/* already running */
1459
1460
    if (var_smtpd_tls_loglevel >= 2)
1461
	msg_info("starting TLS engine");
1462
1463
    /*
1464
     * Initialize the OpenSSL library by the book!
1465
     * To start with, we must initialize the algorithms.
1466
     * We want cleartext error messages instead of just error codes, so we
1467
     * load the error_strings.
1468
     */
1469
    SSL_load_error_strings();
1470
    OpenSSL_add_ssl_algorithms();
1471
1472
 /*
1473
  * Side effect, call a non-existing function to disable TLS usage with an
1474
  * outdated OpenSSL version. There is a security reason (verify_result
1475
  * is not stored with the session data).
1476
  */
1477
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
1478
    needs_openssl_095_or_later();
1479
#endif
1480
1481
    /*
1482
     * Initialize the PRNG Pseudo Random Number Generator with some seed.
1483
     */
1484
    randseed.pid = getpid();
1485
    GETTIMEOFDAY(&randseed.tv);
1486
    RAND_seed(&randseed, sizeof(randseed_t));
1487
1488
    /*
1489
     * Access the external sources for random seed. We will only query them
1490
     * once, this should be sufficient and we will stir our entropy by using
1491
     * the prng-exchange file anyway.
1492
     * For reliability, we don't consider failure to access the additional
1493
     * source fatal, as we can run happily without it (considering that we
1494
     * still have the exchange-file). We also don't care how much entropy
1495
     * we get back, as we must run anyway. We simply stir in the buffer
1496
     * regardless how many bytes are actually in it.
1497
     */
1498
    if (*var_tls_daemon_rand_source) {
1499
	if (!strncmp(var_tls_daemon_rand_source, "dev:", 4)) {
1500
	    /*
1501
	     * Source is a random device
1502
	     */
1503
	    rand_source_dev_fd = open(var_tls_daemon_rand_source + 4, 0, 0);
1504
	    if (rand_source_dev_fd == -1) 
1505
		msg_info("Could not open entropy device %s",
1506
			  var_tls_daemon_rand_source);
1507
	    else {
1508
		if (var_tls_daemon_rand_bytes > 255)
1509
		    var_tls_daemon_rand_bytes = 255;
1510
	        read(rand_source_dev_fd, buffer, var_tls_daemon_rand_bytes);
1511
		RAND_seed(buffer, var_tls_daemon_rand_bytes);
1512
		close(rand_source_dev_fd);
1513
	    }
1514
	} else if (!strncmp(var_tls_daemon_rand_source, "egd:", 4)) {
1515
	    /*
1516
	     * Source is a EGD compatible socket
1517
	     */
1518
	    rand_source_socket_fd = unix_connect(var_tls_daemon_rand_source +4,
1519
						 BLOCKING, 10);
1520
	    if (rand_source_socket_fd == -1)
1521
		msg_info("Could not connect to %s", var_tls_daemon_rand_source);
1522
	    else {
1523
		if (var_tls_daemon_rand_bytes > 255)
1524
		    var_tls_daemon_rand_bytes = 255;
1525
		buffer[0] = 1;
1526
		buffer[1] = var_tls_daemon_rand_bytes;
1527
		if (write(rand_source_socket_fd, buffer, 2) != 2)
1528
		    msg_info("Could not talk to %s",
1529
			     var_tls_daemon_rand_source);
1530
		else if (read(rand_source_socket_fd, buffer, 1) != 1)
1531
		    msg_info("Could not read info from %s",
1532
			     var_tls_daemon_rand_source);
1533
		else {
1534
		    rand_bytes = buffer[0];
1535
		    read(rand_source_socket_fd, buffer, rand_bytes);
1536
		    RAND_seed(buffer, rand_bytes);
1537
		}
1538
		close(rand_source_socket_fd);
1539
	    }
1540
	} else {
1541
	    RAND_load_file(var_tls_daemon_rand_source,
1542
			   var_tls_daemon_rand_bytes);
1543
	}
1544
    }
1545
1546
    if (*var_tls_rand_exch_name) {
1547
	rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
1548
	if (rand_exch_fd != -1)
1549
	    pfixtls_exchange_seed();
1550
    }
1551
1552
    randseed.pid = getpid();
1553
    GETTIMEOFDAY(&randseed.tv);
1554
    RAND_seed(&randseed, sizeof(randseed_t));
1555
1556
    /*
1557
     * The SSL/TLS speficications require the client to send a message in
1558
     * the oldest specification it understands with the highest level it
1559
     * understands in the message.
1560
     * Netscape communicator can still communicate with SSLv2 servers, so it
1561
     * sends out a SSLv2 client hello. To deal with it, our server must be
1562
     * SSLv2 aware (even if we don't like SSLv2), so we need to have the
1563
     * SSLv23 server here. If we want to limit the protocol level, we can
1564
     * add an option to not use SSLv2/v3/TLSv1 later.
1565
     */
1566
    ctx = SSL_CTX_new(SSLv23_server_method());
1567
    if (ctx == NULL) {
1568
	pfixtls_print_errors();
1569
	return (-1);
1570
    };
1571
1572
    /*
1573
     * Here we might set SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1.
1574
     * Of course, the last one would not make sense, since RFC2487 is only
1575
     * defined for TLS, but we also want to accept Netscape communicator
1576
     * requests, and it only supports SSLv3.
1577
     */
1578
    off |= SSL_OP_ALL;		/* Work around all known bugs */
1579
    SSL_CTX_set_options(ctx, off);
1580
1581
    /*
1582
     * Set the info_callback, that will print out messages during
1583
     * communication on demand.
1584
     */
1585
    if (var_smtpd_tls_loglevel >= 2)
1586
	SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
1587
1588
    /*
1589
     * Set the list of ciphers, if explicitely given; otherwise the
1590
     * (reasonable) default list is kept.
1591
     */
1592
    if (strlen(var_smtpd_tls_cipherlist) != 0)
1593
	if (SSL_CTX_set_cipher_list(ctx, var_smtpd_tls_cipherlist) == 0) {
1594
	    pfixtls_print_errors();
1595
	    return (-1);
1596
	}
1597
1598
    /*
1599
     * Now we must add the necessary certificate stuff: A server key, a
1600
     * server certificate, and the CA certificates for both the server
1601
     * cert and the verification of client certificates.
1602
     * As provided by OpenSSL we support two types of CA certificate handling:
1603
     * One possibility is to add all CA certificates to one large CAfile,
1604
     * the other possibility is a directory pointed to by CApath, containing
1605
     * seperate files for each CA pointed on by softlinks named by the hash
1606
     * values of the certificate.
1607
     * The first alternative has the advantage, that the file is opened and
1608
     * read at startup time, so that you don't have the hassle to maintain
1609
     * another copy of the CApath directory for chroot-jail. On the other
1610
     * hand, the file is not really readable.
1611
     */
1612
    if (strlen(var_smtpd_tls_CAfile) == 0)
1613
	CAfile = NULL;
1614
    else
1615
	CAfile = var_smtpd_tls_CAfile;
1616
    if (strlen(var_smtpd_tls_CApath) == 0)
1617
	CApath = NULL;
1618
    else
1619
	CApath = var_smtpd_tls_CApath;
1620
1621
    if (CAfile || CApath) {
1622
	if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
1623
	    msg_info("TLS engine: cannot load CA data");
1624
	    pfixtls_print_errors();
1625
	    return (-1);
1626
	}
1627
	if (!SSL_CTX_set_default_verify_paths(ctx)) {
1628
	    msg_info("TLS engine: cannot set verify paths");
1629
	    pfixtls_print_errors();
1630
	    return (-1);
1631
	}
1632
    }
1633
1634
    /*
1635
     * Now we load the certificate and key from the files and check,
1636
     * whether the cert matches the key (internally done by set_cert_stuff().
1637
     * We cannot run without (we do not support ADH anonymous Diffie-Hellman
1638
     * ciphers as of now).
1639
     * We can use RSA certificates ("cert") and DSA certificates ("dcert"),
1640
     * both can be made available at the same time. The CA certificates for
1641
     * both are handled in the same setup already finished.
1642
     * Which one is used depends on the cipher negotiated (that is: the first
1643
     * cipher listed by the client which does match the server). A client with
1644
     * RSA only (e.g. Netscape) will use the RSA certificate only.
1645
     * A client with openssl-library will use RSA first if not especially
1646
     * changed in the cipher setup.
1647
     */
1648
    if (strlen(var_smtpd_tls_cert_file) == 0)
1649
	s_cert_file = NULL;
1650
    else
1651
	s_cert_file = var_smtpd_tls_cert_file;
1652
    if (strlen(var_smtpd_tls_key_file) == 0)
1653
	s_key_file = NULL;
1654
    else
1655
	s_key_file = var_smtpd_tls_key_file;
1656
1657
    if (strlen(var_smtpd_tls_dcert_file) == 0)
1658
	s_dcert_file = NULL;
1659
    else
1660
	s_dcert_file = var_smtpd_tls_dcert_file;
1661
    if (strlen(var_smtpd_tls_dkey_file) == 0)
1662
	s_dkey_file = NULL;
1663
    else
1664
	s_dkey_file = var_smtpd_tls_dkey_file;
1665
1666
    if (s_cert_file) {
1667
	if (!set_cert_stuff(ctx, s_cert_file, s_key_file)) {
1668
	    msg_info("TLS engine: cannot load RSA cert/key data");
1669
	    pfixtls_print_errors();
1670
	    return (-1);
1671
	}
1672
    }
1673
    if (s_dcert_file) {
1674
	if (!set_cert_stuff(ctx, s_dcert_file, s_dkey_file)) {
1675
	    msg_info("TLS engine: cannot load DSA cert/key data");
1676
	    pfixtls_print_errors();
1677
	    return (-1);
1678
	}
1679
    }
1680
    if (!s_cert_file && !s_dcert_file) {
1681
	msg_info("TLS engine: do need at least RSA _or_ DSA cert/key data");
1682
	return (-1);
1683
    }
1684
1685
    /*
1686
     * Sometimes a temporary RSA key might be needed by the OpenSSL
1687
     * library. The OpenSSL doc indicates, that this might happen when
1688
     * export ciphers are in use. We have to provide one, so well, we
1689
     * just do it.
1690
     */
1691
    SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
1692
1693
    /*
1694
     * We might also need dh parameters, which can either be loaded from
1695
     * file (preferred) or we simply take the compiled in values.
1696
     * First, set the callback that will select the values when requested,
1697
     * then load the (possibly) available DH parameters from files.
1698
     * We are generous with the error handling, since we do have default
1699
     * values compiled in, so we will not abort but just log the error message.
1700
     */
1701
    SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_cb);
1702
    if (strlen(var_smtpd_tls_dh1024_param_file) != 0) {
1703
	if ((paramfile = fopen(var_smtpd_tls_dh1024_param_file, "r")) != NULL) {
1704
	    dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
1705
	    if (dh_1024 == NULL) {
1706
		msg_info("TLS engine: cannot load 1024bit DH parameters");
1707
		pfixtls_print_errors();
1708
	    }
1709
	}
1710
	else {
1711
	    msg_info("TLS engine: cannot load 1024bit DH parameters: %s: %s",
1712
		     var_smtpd_tls_dh1024_param_file, strerror(errno));
1713
	}
1714
    }
1715
    if (strlen(var_smtpd_tls_dh512_param_file) != 0) {
1716
	if ((paramfile = fopen(var_smtpd_tls_dh512_param_file, "r")) != NULL) {
1717
	    dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
1718
	    if (dh_512 == NULL) {
1719
		msg_info("TLS engine: cannot load 512bit DH parameters");
1720
		pfixtls_print_errors();
1721
	    }
1722
	}
1723
	else {
1724
	    msg_info("TLS engine: cannot load 512bit DH parameters: %s: %s",
1725
		     var_smtpd_tls_dh512_param_file, strerror(errno));
1726
	}
1727
    }
1728
1729
    /*
1730
     * If we want to check client certificates, we have to indicate it
1731
     * in advance. By now we only allow to decide on a global basis.
1732
     * If we want to allow certificate based relaying, we must ask the
1733
     * client to provide one with SSL_VERIFY_PEER. The client now can
1734
     * decide, whether it provides one or not. We can enforce a failure
1735
     * of the negotiation with SSL_VERIFY_FAIL_IF_NO_PEER_CERT, if we
1736
     * do not allow a connection without one.
1737
     * In the "server hello" following the initialization by the "client hello"
1738
     * the server must provide a list of CAs it is willing to accept.
1739
     * Some clever clients will then select one from the list of available
1740
     * certificates matching these CAs. Netscape Communicator will present
1741
     * the list of certificates for selecting the one to be sent, or it will
1742
     * issue a warning, if there is no certificate matching the available
1743
     * CAs.
1744
     *
1745
     * With regard to the purpose of the certificate for relaying, we might
1746
     * like a later negotiation, maybe relaying would already be allowed
1747
     * for other reasons, but this would involve severe changes in the
1748
     * internal postfix logic, so we have to live with it the way it is.
1749
     */
1750
    if (askcert)
1751
	verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
1752
    SSL_CTX_set_verify(ctx, verify_flags, verify_callback);
1753
    SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
1754
1755
    /*
1756
     * Initialize the session cache. We only want external caching to
1757
     * synchronize between server sessions, so we set it to a minimum value
1758
     * of 1. If the external cache is disabled, we won't cache at all.
1759
     * The recall of old sessions "get" and save to disk of just created
1760
     * sessions "new" is handled by the appropriate callback functions.
1761
     *
1762
     * We must not forget to set a session id context to identify to which
1763
     * kind of server process the session was related. In our case, the
1764
     * context is just the name of the patchkit: "Postfix/TLS".
1765
     */
1766
    SSL_CTX_sess_set_cache_size(ctx, 1);
1767
    SSL_CTX_set_timeout(ctx, var_smtpd_tls_scache_timeout);
1768
    SSL_CTX_set_session_id_context(ctx, (void*)&server_session_id_context,
1769
                sizeof(server_session_id_context));
1770
1771
    /*
1772
     * The session cache is realized by an external database file, that
1773
     * must be opened before going to chroot jail. Since the session cache
1774
     * data can become quite large, "[n]dbm" cannot be used as it has a
1775
     * size limit that is by far to small.
1776
     */
1777
    if (*var_smtpd_tls_scache_db) {
1778
	/*
1779
	 * Insert a test against other dbms here, otherwise while writing
1780
	 * a session (content to large), we will receive a fatal error!
1781
	 */
1782
	if (strncmp(var_smtpd_tls_scache_db, "sdbm:", 5))
1783
	    msg_warn("Only sdbm: type allowed for %s",
1784
		     var_smtpd_tls_scache_db);
1785
	else
1786
	    scache_db = dict_open(var_smtpd_tls_scache_db, O_RDWR,
1787
	      DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
1788
	if (scache_db) {
1789
	    SSL_CTX_set_session_cache_mode(ctx,
1790
			SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_AUTO_CLEAR);
1791
	    SSL_CTX_sess_set_get_cb(ctx, get_session_cb);
1792
	    SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
1793
	    SSL_CTX_sess_set_remove_cb(ctx, remove_session_cb);
1794
	}
1795
	else
1796
	    msg_warn("Could not open session cache %s",
1797
		     var_smtpd_tls_scache_db);
1798
    }
1799
1800
    /*
1801
     * Finally create the global index to access TLScontext information
1802
     * inside verify_callback.
1803
     */
1804
    TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
1805
					    NULL, NULL, NULL);
1806
1807
    pfixtls_serverengine = 1;
1808
    return (0);
1809
}
1810
1811
 /*
1812
  * This is the actual startup routine for the connection. We expect
1813
  * that the buffers are flushed and the "220 Ready to start TLS" was
1814
  * send to the client, so that we can immediately can start the TLS
1815
  * handshake process.
1816
  */
1817
int     pfixtls_start_servertls(VSTREAM *stream, int timeout,
1818
				const char *peername, const char *peeraddr,
1819
				tls_info_t *tls_info, int requirecert)
1820
{
1821
    int     sts;
1822
    int     j;
1823
    int verify_flags;
1824
    unsigned int n;
1825
    TLScontext_t *TLScontext;
1826
    SSL_SESSION *session;
1827
    SSL_CIPHER *cipher;
1828
    X509   *peer;
1829
1830
    if (!pfixtls_serverengine) {		/* should never happen */
1831
	msg_info("tls_engine not running");
1832
	return (-1);
1833
    }
1834
    if (var_smtpd_tls_loglevel >= 1)
1835
	msg_info("setting up TLS connection from %s[%s]", peername, peeraddr);
1836
1837
    /*
1838
     * Allocate a new TLScontext for the new connection and get an SSL
1839
     * structure. Add the location of TLScontext to the SSL to later
1840
     * retrieve the information inside the verify_callback().
1841
     */
1842
    TLScontext = (TLScontext_t *)mymalloc(sizeof(TLScontext_t));
1843
    if (!TLScontext) {
1844
	msg_fatal("Could not allocate 'TLScontext' with mymalloc");
1845
    }
1846
    if ((TLScontext->con = (SSL *) SSL_new(ctx)) == NULL) {
1847
	msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
1848
	pfixtls_print_errors();
1849
	myfree((char *)TLScontext);
1850
	return (-1);
1851
    }
1852
    if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
1853
	msg_info("Could not set application data for 'TLScontext->con'");
1854
	pfixtls_print_errors();
1855
	SSL_free(TLScontext->con);
1856
	myfree((char *)TLScontext);
1857
	return (-1);
1858
    }
1859
1860
    /*
1861
     * Set the verification parameters to be checked in verify_callback().
1862
     */
1863
    if (requirecert) {
1864
	verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
1865
	verify_flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1866
	TLScontext->enforce_verify_errors = 1;
1867
        SSL_set_verify(TLScontext->con, verify_flags, verify_callback);
1868
    }
1869
    else {
1870
	TLScontext->enforce_verify_errors = 0;
1871
    }
1872
    TLScontext->enforce_CN = 0;
1873
1874
    /*
1875
     * The TLS connection is realized by a BIO_pair, so obtain the pair.
1876
     */
1877
    if (!BIO_new_bio_pair(&TLScontext->internal_bio, BIO_bufsiz,
1878
			  &TLScontext->network_bio, BIO_bufsiz)) {
1879
	msg_info("Could not obtain BIO_pair");
1880
	pfixtls_print_errors();
1881
	SSL_free(TLScontext->con);
1882
	myfree((char *)TLScontext);
1883
	return (-1);
1884
    }
1885
1886
    /*
1887
     * Before really starting anything, try to seed the PRNG a little bit
1888
     * more.
1889
     */
1890
    pfixtls_stir_seed();
1891
    pfixtls_exchange_seed();
1892
1893
    /*
1894
     * Initialize the SSL connection to accept state. This should not be
1895
     * necessary anymore since 0.9.3, but the call is still in the library
1896
     * and maintaining compatibility never hurts.
1897
     */
1898
    SSL_set_accept_state(TLScontext->con);
1899
1900
    /*
1901
     * Connect the SSL-connection with the postfix side of the BIO-pair for
1902
     * reading and writing.
1903
     */
1904
     SSL_set_bio(TLScontext->con, TLScontext->internal_bio,
1905
		 TLScontext->internal_bio);
1906
1907
    /*
1908
     * If the debug level selected is high enough, all of the data is
1909
     * dumped: 3 will dump the SSL negotiation, 4 will dump everything.
1910
     *
1911
     * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
1912
     * Well there is a BIO below the SSL routines that is automatically
1913
     * created for us, so we can use it for debugging purposes.
1914
     */
1915
    if (var_smtpd_tls_loglevel >= 3)
1916
	BIO_set_callback(SSL_get_rbio(TLScontext->con), bio_dump_cb);
1917
1918
1919
    /* Dump the negotiation for loglevels 3 and 4 */
1920
    if (var_smtpd_tls_loglevel >= 3)
1921
	do_dump = 1;
1922
1923
    /*
1924
     * Now we expect the negotiation to begin. This whole process is like a
1925
     * black box for us. We totally have to rely on the routines build into
1926
     * the OpenSSL library. The only thing we can do we already have done
1927
     * by choosing our own callbacks for session caching and certificate
1928
     * verification.
1929
     *
1930
     * Error handling:
1931
     * If the SSL handhake fails, we print out an error message and remove
1932
     * everything that might be there. A session has to be removed anyway,
1933
     * because RFC2246 requires it.
1934
     */
1935
    sts = do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
1936
			   SSL_accept, NULL, NULL, NULL, 0);
1937
    if (sts <= 0) {
1938
	msg_info("SSL_accept error from %s[%s]: %d", peername, peeraddr, sts);
1939
	pfixtls_print_errors();
1940
	SSL_free(TLScontext->con);
1941
	myfree((char *)TLScontext);
1942
	return (-1);
1943
    }
1944
1945
    /* Only loglevel==4 dumps everything */
1946
    if (var_smtpd_tls_loglevel < 4)
1947
	do_dump = 0;
1948
1949
    /*
1950
     * Lets see, whether a peer certificate is available and what is
1951
     * the actual information. We want to save it for later use.
1952
     */
1953
    peer = SSL_get_peer_certificate(TLScontext->con);
1954
    if (peer != NULL) {
1955
	if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
1956
	    tls_info->peer_verified = 1;
1957
1958
	X509_NAME_oneline(X509_get_subject_name(peer),
1959
			  TLScontext->peer_subject, CCERT_BUFSIZ);
1960
	if (var_smtpd_tls_loglevel >= 2)
1961
	    msg_info("subject=%s", TLScontext->peer_subject);
1962
	tls_info->peer_subject = TLScontext->peer_subject;
1963
	X509_NAME_oneline(X509_get_issuer_name(peer),
1964
			  TLScontext->peer_issuer, CCERT_BUFSIZ);
1965
	if (var_smtpd_tls_loglevel >= 2)
1966
	    msg_info("issuer=%s", TLScontext->peer_issuer);
1967
	tls_info->peer_issuer = TLScontext->peer_issuer;
1968
	if (X509_digest(peer, EVP_md5(), TLScontext->md, &n)) {
1969
	    for (j = 0; j < (int) n; j++) {
1970
		TLScontext->fingerprint[j * 3] =
1971
			hexcodes[(TLScontext->md[j] & 0xf0) >> 4];
1972
		TLScontext->fingerprint[(j * 3) + 1] =
1973
			hexcodes[(TLScontext->md[j] & 0x0f)];
1974
		if (j + 1 != (int) n)
1975
		    TLScontext->fingerprint[(j * 3) + 2] = ':';
1976
		else
1977
		    TLScontext->fingerprint[(j * 3) + 2] = '\0';
1978
	    }
1979
	    if (var_smtpd_tls_loglevel >= 1)
1980
		msg_info("fingerprint=%s", TLScontext->fingerprint);
1981
	    tls_info->peer_fingerprint = TLScontext->fingerprint;
1982
	}
1983
1984
	TLScontext->peer_CN[0] = '\0';
1985
	if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
1986
			NID_commonName, TLScontext->peer_CN, CCERT_BUFSIZ)) {
1987
	    msg_info("Could not parse client's subject CN");
1988
	    pfixtls_print_errors();
1989
	}
1990
	tls_info->peer_CN = TLScontext->peer_CN;
1991
1992
	TLScontext->issuer_CN[0] = '\0';
1993
	if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
1994
			NID_commonName, TLScontext->issuer_CN, CCERT_BUFSIZ)) {
1995
	    msg_info("Could not parse client's issuer CN");
1996
	    pfixtls_print_errors();
1997
	}
1998
	if (!TLScontext->issuer_CN[0]) {
1999
	    /* No issuer CN field, use Organization instead */
2000
	    if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
2001
		NID_organizationName, TLScontext->issuer_CN, CCERT_BUFSIZ)) {
2002
		msg_info("Could not parse client's issuer Organization");
2003
		pfixtls_print_errors();
2004
	    }
2005
	}
2006
	tls_info->issuer_CN = TLScontext->issuer_CN;
2007
2008
	if (var_smtpd_tls_loglevel >= 1) {
2009
	    if (tls_info->peer_verified)
2010
		msg_info("Verified: subject_CN=%s, issuer=%s",
2011
			 TLScontext->peer_CN, TLScontext->issuer_CN);
2012
	    else
2013
		msg_info("Unverified: subject_CN=%s, issuer=%s",
2014
			 TLScontext->peer_CN, TLScontext->issuer_CN);
2015
	}
2016
2017
	X509_free(peer);
2018
    }
2019
2020
    /*
2021
     * At this point we should have a certificate when required.
2022
     * We may however have a cached session, so the callback would never
2023
     * be called. We therefore double-check to make sure and remove the
2024
     * session, if applicable.
2025
     */
2026
    if (requirecert) {
2027
	if (!tls_info->peer_verified || !tls_info->peer_CN) {
2028
	    msg_info("Re-used session without peer certificate removed");
2029
	    session = SSL_get_session(TLScontext->con);
2030
	    SSL_CTX_remove_session(ctx, session);
2031
	    return (-1);
2032
	}
2033
    }
2034
2035
    /*
2036
     * Finally, collect information about protocol and cipher for logging
2037
     */
2038
    tls_info->protocol = SSL_get_version(TLScontext->con);
2039
    cipher = SSL_get_current_cipher(TLScontext->con);
2040
    tls_info->cipher_name = SSL_CIPHER_get_name(cipher);
2041
    tls_info->cipher_usebits = SSL_CIPHER_get_bits(cipher,
2042
						 &(tls_info->cipher_algbits));
2043
2044
    pfixtls_serveractive = 1;
2045
2046
    /*
2047
     * The TLS engine is active, switch to the pfixtls_timed_read/write()
2048
     * functions and store the context.
2049
     */
2050
    vstream_control(stream,
2051
		    VSTREAM_CTL_READ_FN, pfixtls_timed_read,
2052
		    VSTREAM_CTL_WRITE_FN, pfixtls_timed_write,
2053
		    VSTREAM_CTL_CONTEXT, (void *)TLScontext,
2054
		    VSTREAM_CTL_END);
2055
2056
    msg_info("TLS connection established from %s[%s]: %s with cipher %s (%d/%d bits)",
2057
	     peername, peeraddr,
2058
	     tls_info->protocol, tls_info->cipher_name,
2059
	     tls_info->cipher_usebits, tls_info->cipher_algbits);
2060
    pfixtls_stir_seed();
2061
2062
    return (0);
2063
}
2064
2065
 /*
2066
  * Shut down the TLS connection, that does mean: remove all the information
2067
  * and reset the flags! This is needed if the actual running smtpd is to
2068
  * be restarted. We do not give back any value, as there is nothing to
2069
  * be reported.
2070
  * Since our session cache is external, we will remove the session from
2071
  * memory in any case. The SSL_CTX_flush_sessions might be redundant here,
2072
  * I however want to make sure nothing is left.
2073
  * RFC2246 requires us to remove sessions if something went wrong, as
2074
  * indicated by the "failure" value, so we remove it from the external
2075
  * cache, too. 
2076
  */
2077
int     pfixtls_stop_servertls(VSTREAM *stream, int timeout, int failure,
2078
			       tls_info_t *tls_info)
2079
{
2080
    TLScontext_t *TLScontext;
2081
    int retval;
2082
2083
    if (pfixtls_serveractive) {
2084
	TLScontext = (TLScontext_t *)vstream_context(stream);
2085
	/*
2086
	 * Perform SSL_shutdown() twice, as the first attempt may return
2087
	 * to early: it will only send out the shutdown alert but it will
2088
	 * not wait for the peer's shutdown alert. Therefore, when we are
2089
	 * the first party to send the alert, we must call SSL_shutdown()
2090
	 * again.
2091
	 * On failure we don't want to resume the session, so we will not
2092
	 * perform SSL_shutdown() and the session will be removed as being
2093
	 * bad.
2094
	 */
2095
	if (!failure) {
2096
            retval = do_tls_operation(vstream_fileno(stream), timeout,
2097
				TLScontext, SSL_shutdown, NULL, NULL, NULL, 0);
2098
	    if (retval == 0)
2099
		do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
2100
				SSL_shutdown, NULL, NULL, NULL, 0);
2101
	}
2102
	/*
2103
	 * Free the SSL structure and the BIOs. Warning: the internal_bio is
2104
	 * connected to the SSL structure and is automatically freed with
2105
	 * it. Do not free it again (core dump)!!
2106
	 * Only free the network_bio.
2107
	 */
2108
	SSL_free(TLScontext->con);
2109
	BIO_free(TLScontext->network_bio);
2110
	myfree((char *)TLScontext);
2111
        vstream_control(stream,
2112
		    VSTREAM_CTL_READ_FN, (VSTREAM_FN) NULL,
2113
		    VSTREAM_CTL_WRITE_FN, (VSTREAM_FN) NULL,
2114
		    VSTREAM_CTL_CONTEXT, (void *) NULL,
2115
		    VSTREAM_CTL_END);
2116
	SSL_CTX_flush_sessions(ctx, time(NULL));
2117
2118
	pfixtls_stir_seed();
2119
	pfixtls_exchange_seed();
2120
2121
	*tls_info = tls_info_zero;
2122
	pfixtls_serveractive = 0;
2123
2124
    }
2125
2126
    return (0);
2127
}
2128
2129
2130
 /*
2131
  * This is the setup routine for the SSL client. As smtpd might be called
2132
  * more than once, we only want to do the initialization one time.
2133
  *
2134
  * The skeleton of this function is taken from OpenSSL apps/s_client.c.
2135
  */
2136
2137
int     pfixtls_init_clientengine(int verifydepth)
2138
{
2139
    int     off = 0;
2140
    int     verify_flags = SSL_VERIFY_NONE;
2141
    int     rand_bytes;
2142
    int     rand_source_dev_fd;
2143
    int     rand_source_socket_fd;
2144
    unsigned char buffer[255];
2145
    char   *CApath;
2146
    char   *CAfile;
2147
    char   *c_cert_file;
2148
    char   *c_key_file;
2149
2150
2151
    if (pfixtls_clientengine)
2152
	return (0);				/* already running */
2153
2154
    if (var_smtp_tls_loglevel >= 2)
2155
	msg_info("starting TLS engine");
2156
2157
    /*
2158
     * Initialize the OpenSSL library by the book!
2159
     * To start with, we must initialize the algorithms.
2160
     * We want cleartext error messages instead of just error codes, so we
2161
     * load the error_strings.
2162
     */ 
2163
    SSL_load_error_strings();
2164
    OpenSSL_add_ssl_algorithms();
2165
2166
 /*
2167
  * Side effect, call a non-existing function to disable TLS usage with an
2168
  * outdated OpenSSL version. There is a security reason (verify_result
2169
  * is not stored with the session data).
2170
  */
2171
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
2172
    needs_openssl_095_or_later();
2173
#endif
2174
2175
    /*
2176
     * Initialize the PRNG Pseudo Random Number Generator with some seed.
2177
     */
2178
    randseed.pid = getpid();
2179
    GETTIMEOFDAY(&randseed.tv);
2180
    RAND_seed(&randseed, sizeof(randseed_t));
2181
2182
    /*
2183
     * Access the external sources for random seed. We will only query them
2184
     * once, this should be sufficient and we will stir our entropy by using
2185
     * the prng-exchange file anyway.
2186
     * For reliability, we don't consider failure to access the additional
2187
     * source fatal, as we can run happily without it (considering that we
2188
     * still have the exchange-file). We also don't care how much entropy
2189
     * we get back, as we must run anyway. We simply stir in the buffer
2190
     * regardless how many bytes are actually in it.
2191
     */
2192
    if (*var_tls_daemon_rand_source) {
2193
	if (!strncmp(var_tls_daemon_rand_source, "dev:", 4)) {
2194
	    /*
2195
	     * Source is a random device
2196
	     */
2197
	    rand_source_dev_fd = open(var_tls_daemon_rand_source + 4, 0, 0);
2198
	    if (rand_source_dev_fd == -1) 
2199
		msg_info("Could not open entropy device %s",
2200
			  var_tls_daemon_rand_source);
2201
	    else {
2202
		if (var_tls_daemon_rand_bytes > 255)
2203
		    var_tls_daemon_rand_bytes = 255;
2204
	        read(rand_source_dev_fd, buffer, var_tls_daemon_rand_bytes);
2205
		RAND_seed(buffer, var_tls_daemon_rand_bytes);
2206
		close(rand_source_dev_fd);
2207
	    }
2208
	} else if (!strncmp(var_tls_daemon_rand_source, "egd:", 4)) {
2209
	    /*
2210
	     * Source is a EGD compatible socket
2211
	     */
2212
	    rand_source_socket_fd = unix_connect(var_tls_daemon_rand_source +4,
2213
						 BLOCKING, 10);
2214
	    if (rand_source_socket_fd == -1)
2215
		msg_info("Could not connect to %s", var_tls_daemon_rand_source);
2216
	    else {
2217
		if (var_tls_daemon_rand_bytes > 255)
2218
		    var_tls_daemon_rand_bytes = 255;
2219
		buffer[0] = 1;
2220
		buffer[1] = var_tls_daemon_rand_bytes;
2221
		if (write(rand_source_socket_fd, buffer, 2) != 2)
2222
		    msg_info("Could not talk to %s",
2223
			     var_tls_daemon_rand_source);
2224
		else if (read(rand_source_socket_fd, buffer, 1) != 1)
2225
		    msg_info("Could not read info from %s",
2226
			     var_tls_daemon_rand_source);
2227
		else {
2228
		    rand_bytes = buffer[0];
2229
		    read(rand_source_socket_fd, buffer, rand_bytes);
2230
		    RAND_seed(buffer, rand_bytes);
2231
		}
2232
		close(rand_source_socket_fd);
2233
	    }
2234
	} else {
2235
	    RAND_load_file(var_tls_daemon_rand_source,
2236
			   var_tls_daemon_rand_bytes);
2237
	}
2238
    }
2239
2240
    if (*var_tls_rand_exch_name) {
2241
	rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
2242
	if (rand_exch_fd != -1)
2243
	    pfixtls_exchange_seed();
2244
    }
2245
2246
    randseed.pid = getpid();
2247
    GETTIMEOFDAY(&randseed.tv);
2248
    RAND_seed(&randseed, sizeof(randseed_t));
2249
2250
    /*
2251
     * The SSL/TLS speficications require the client to send a message in
2252
     * the oldest specification it understands with the highest level it
2253
     * understands in the message.
2254
     * RFC2487 is only specified for TLSv1, but we want to be as compatible
2255
     * as possible, so we will start off with a SSLv2 greeting allowing
2256
     * the best we can offer: TLSv1.
2257
     * We can restrict this with the options setting later, anyhow.
2258
     */
2259
    ctx = SSL_CTX_new(SSLv23_client_method());
2260
    if (ctx == NULL) {
2261
	pfixtls_print_errors();
2262
	return (-1);
2263
    };
2264
2265
    /*
2266
     * Here we might set SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1.
2267
     * Of course, the last one would not make sense, since RFC2487 is only
2268
     * defined for TLS, but we don't know what is out there. So leave things
2269
     * completely open, as of today.
2270
     */
2271
    off |= SSL_OP_ALL;		/* Work around all known bugs */
2272
    SSL_CTX_set_options(ctx, off);
2273
2274
    /*
2275
     * Set the info_callback, that will print out messages during
2276
     * communication on demand.
2277
     */
2278
    if (var_smtp_tls_loglevel >= 2)
2279
	SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
2280
2281
    /*
2282
     * Set the list of ciphers, if explicitely given; otherwise the
2283
     * (reasonable) default list is kept.
2284
     */
2285
    if (strlen(var_smtp_tls_cipherlist) != 0)
2286
	if (SSL_CTX_set_cipher_list(ctx, var_smtp_tls_cipherlist) == 0) {
2287
	    pfixtls_print_errors();
2288
	    return (-1);
2289
	}
2290
2291
    /*
2292
     * Now we must add the necessary certificate stuff: A client key, a
2293
     * client certificate, and the CA certificates for both the client
2294
     * cert and the verification of server certificates.
2295
     * In fact, we do not need a client certificate,  so the certificates
2296
     * are only loaded (and checked), if supplied. A clever client would
2297
     * handle multiple client certificates and decide based on the list
2298
     * of acceptable CAs, sent by the server, which certificate to submit.
2299
     * OpenSSL does however not do this and also has no callback hoods to
2300
     * easily realize it.
2301
     *
2302
     * As provided by OpenSSL we support two types of CA certificate handling:
2303
     * One possibility is to add all CA certificates to one large CAfile,
2304
     * the other possibility is a directory pointed to by CApath, containing
2305
     * seperate files for each CA pointed on by softlinks named by the hash
2306
     * values of the certificate.
2307
     * The first alternative has the advantage, that the file is opened and
2308
     * read at startup time, so that you don't have the hassle to maintain
2309
     * another copy of the CApath directory for chroot-jail. On the other
2310
     * hand, the file is not really readable.
2311
     */ 
2312
    if (strlen(var_smtp_tls_CAfile) == 0)
2313
	CAfile = NULL;
2314
    else
2315
	CAfile = var_smtp_tls_CAfile;
2316
    if (strlen(var_smtp_tls_CApath) == 0)
2317
	CApath = NULL;
2318
    else
2319
	CApath = var_smtp_tls_CApath;
2320
    if (CAfile || CApath) {
2321
	if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
2322
	    msg_info("TLS engine: cannot load CA data");
2323
	    pfixtls_print_errors();
2324
	    return (-1);
2325
	}
2326
	if (!SSL_CTX_set_default_verify_paths(ctx)) {
2327
	    msg_info("TLS engine: cannot set verify paths");
2328
	    pfixtls_print_errors();
2329
	    return (-1);
2330
	}
2331
    }
2332
2333
    if (strlen(var_smtp_tls_cert_file) == 0)
2334
	c_cert_file = NULL;
2335
    else
2336
	c_cert_file = var_smtp_tls_cert_file;
2337
    if (strlen(var_smtp_tls_key_file) == 0)
2338
	c_key_file = NULL;
2339
    else
2340
	c_key_file = var_smtp_tls_key_file;
2341
    if (c_cert_file || c_key_file)
2342
	if (!set_cert_stuff(ctx, c_cert_file, c_key_file)) {
2343
	    msg_info("TLS engine: cannot load cert/key data");
2344
	    pfixtls_print_errors();
2345
	    return (-1);
2346
	}
2347
2348
    /*
2349
     * Sometimes a temporary RSA key might be needed by the OpenSSL
2350
     * library. The OpenSSL doc indicates, that this might happen when
2351
     * export ciphers are in use. We have to provide one, so well, we
2352
     * just do it.
2353
     */
2354
    SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
2355
2356
    /*
2357
     * Finally, the setup for the server certificate checking, done
2358
     * "by the book".
2359
     */
2360
    SSL_CTX_set_verify(ctx, verify_flags, verify_callback);
2361
2362
    /*
2363
     * Initialize the session cache. We only want external caching to
2364
     * synchronize between server sessions, so we set it to a minimum value
2365
     * of 1. If the external cache is disabled, we won't cache at all.
2366
     *
2367
     * In case of the client, there is no callback used in OpenSSL, so
2368
     * we must call the session cache functions manually during the process.
2369
     */
2370
    SSL_CTX_sess_set_cache_size(ctx, 1);
2371
    SSL_CTX_set_timeout(ctx, var_smtp_tls_scache_timeout);
2372
2373
    /*
2374
     * The session cache is realized by an external database file, that
2375
     * must be opened before going to chroot jail. Since the session cache
2376
     * data can become quite large, "[n]dbm" cannot be used as it has a
2377
     * size limit that is by far to small.
2378
     */
2379
    if (*var_smtp_tls_scache_db) {
2380
	/*
2381
	 * Insert a test against other dbms here, otherwise while writing
2382
	 * a session (content to large), we will receive a fatal error!
2383
	 */
2384
	if (strncmp(var_smtp_tls_scache_db, "sdbm:", 5))
2385
	    msg_warn("Only sdbm: type allowed for %s",
2386
		     var_smtp_tls_scache_db);
2387
	else
2388
	    scache_db = dict_open(var_smtp_tls_scache_db, O_RDWR,
2389
	      DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
2390
	if (!scache_db)
2391
	    msg_warn("Could not open session cache %s",
2392
		     var_smtp_tls_scache_db);
2393
	/*
2394
	 * It is practical to have OpenSSL automatically save newly created
2395
	 * sessions for us by callback. Therefore we have to enable the
2396
	 * internal session cache for the client side. Disable automatic
2397
	 * clearing, as smtp has limited lifetime anyway and we can call
2398
	 * the cleanup routine at will.
2399
	 */
2400
	SSL_CTX_set_session_cache_mode(ctx,
2401
			SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_NO_AUTO_CLEAR);
2402
	SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
2403
    }
2404
   
2405
    /*
2406
     * Finally create the global index to access TLScontext information
2407
     * inside verify_callback.
2408
     */
2409
    TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
2410
					    NULL, NULL, NULL);
2411
    TLSpeername_index = SSL_SESSION_get_ex_new_index(0,
2412
					    "TLSpeername ex_data index",
2413
					    new_peername_func,
2414
					    dup_peername_func,
2415
					    free_peername_func);
2416
2417
    pfixtls_clientengine = 1;
2418
    return (0);
2419
}
2420
2421
 /*
2422
  * This is the actual startup routine for the connection. We expect
2423
  * that the buffers are flushed and the "220 Ready to start TLS" was
2424
  * received by us, so that we can immediately can start the TLS
2425
  * handshake process.
2426
  */
2427
int     pfixtls_start_clienttls(VSTREAM *stream, int timeout,
2428
			        int enforce_peername,
2429
				const char *peername,
2430
				tls_info_t *tls_info)
2431
{
2432
    int     sts;
2433
    SSL_SESSION *session, *old_session;
2434
    SSL_CIPHER *cipher;
2435
    X509   *peer;
2436
    int     verify_flags;
2437
    TLScontext_t *TLScontext;
2438
2439
    if (!pfixtls_clientengine) {		/* should never happen */
2440
	msg_info("tls_engine not running");
2441
	return (-1);
2442
    }
2443
    if (var_smtpd_tls_loglevel >= 1)
2444
	msg_info("setting up TLS connection to %s", peername);
2445
2446
    /*
2447
     * Allocate a new TLScontext for the new connection and get an SSL
2448
     * structure. Add the location of TLScontext to the SSL to later
2449
     * retrieve the information inside the verify_callback().
2450
     */
2451
    TLScontext = (TLScontext_t *)mymalloc(sizeof(TLScontext_t));
2452
    if (!TLScontext) {
2453
	msg_fatal("Could not allocate 'TLScontext' with mymalloc");
2454
    }
2455
    if ((TLScontext->con = (SSL *) SSL_new(ctx)) == NULL) {
2456
	msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
2457
	pfixtls_print_errors();
2458
	myfree((char *)TLScontext);
2459
	return (-1);
2460
    }
2461
    if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
2462
	msg_info("Could not set application data for 'TLScontext->con'");
2463
	pfixtls_print_errors();
2464
	SSL_free(TLScontext->con);
2465
	myfree((char *)TLScontext);
2466
	return (-1);
2467
    }
2468
2469
    /*
2470
     * Set the verification parameters to be checked in verify_callback().
2471
     */
2472
    if (enforce_peername) {
2473
	verify_flags = SSL_VERIFY_PEER;
2474
	TLScontext->enforce_verify_errors = 1;
2475
	TLScontext->enforce_CN = 1;
2476
        SSL_set_verify(TLScontext->con, verify_flags, verify_callback);
2477
    }
2478
    else {
2479
	TLScontext->enforce_verify_errors = 0;
2480
	TLScontext->enforce_CN = 0;
2481
    }
2482
2483
    /*
2484
     * The TLS connection is realized by a BIO_pair, so obtain the pair.
2485
     */
2486
    if (!BIO_new_bio_pair(&TLScontext->internal_bio, BIO_bufsiz,
2487
			  &TLScontext->network_bio, BIO_bufsiz)) {
2488
	msg_info("Could not obtain BIO_pair");
2489
	pfixtls_print_errors();
2490
	SSL_free(TLScontext->con);
2491
	myfree((char *)TLScontext);
2492
	return (-1);
2493
    }
2494
2495
    old_session = NULL;
2496
2497
    /*
2498
     * Find out the hashed HostID for the client cache and try to
2499
     * load the session from the cache.
2500
     */
2501
    strncpy(TLScontext->peername_save, peername, ID_MAXLENGTH + 1);
2502
    TLScontext->peername_save[ID_MAXLENGTH] = '\0';  /* just in case */
2503
    (void)lowercase(TLScontext->peername_save);
2504
    if (scache_db) {
2505
	old_session = load_clnt_session(peername, enforce_peername);
2506
	if (old_session) {
2507
	   SSL_set_session(TLScontext->con, old_session);
2508
#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)
2509
	    /*
2510
	     * Ugly Hack: OpenSSL before 0.9.6a does not store the verify
2511
	     * result in sessions for the client side.
2512
	     * We modify the session directly which is version specific,
2513
	     * but this bug is version specific, too.
2514
	     *
2515
	     * READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before
2516
	     * beta1 have this bug, it has been fixed during development
2517
	     * of 0.9.6a. The development version of 0.9.7 can have this
2518
	     * bug, too. It has been fixed on 2000/11/29.
2519
	     */
2520
	    SSL_set_verify_result(TLScontext->con, old_session->verify_result);
2521
#endif
2522
	   
2523
	}
2524
    }
2525
2526
    /*
2527
     * Before really starting anything, try to seed the PRNG a little bit
2528
     * more.
2529
     */
2530
    pfixtls_stir_seed();
2531
    pfixtls_exchange_seed();
2532
2533
    /*
2534
     * Initialize the SSL connection to connect state. This should not be
2535
     * necessary anymore since 0.9.3, but the call is still in the library
2536
     * and maintaining compatibility never hurts.
2537
     */
2538
    SSL_set_connect_state(TLScontext->con);
2539
2540
    /*
2541
     * Connect the SSL-connection with the postfix side of the BIO-pair for
2542
     * reading and writing.
2543
     */
2544
    SSL_set_bio(TLScontext->con, TLScontext->internal_bio,
2545
		TLScontext->internal_bio);
2546
2547
    /*
2548
     * If the debug level selected is high enough, all of the data is
2549
     * dumped: 3 will dump the SSL negotiation, 4 will dump everything.
2550
     *
2551
     * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
2552
     * Well there is a BIO below the SSL routines that is automatically
2553
     * created for us, so we can use it for debugging purposes.
2554
     */
2555
    if (var_smtp_tls_loglevel >= 3)
2556
	BIO_set_callback(SSL_get_rbio(TLScontext->con), bio_dump_cb);
2557
2558
2559
    /* Dump the negotiation for loglevels 3 and 4 */
2560
    if (var_smtp_tls_loglevel >= 3)
2561
	do_dump = 1;
2562
2563
    /*
2564
     * Now we expect the negotiation to begin. This whole process is like a
2565
     * black box for us. We totally have to rely on the routines build into
2566
     * the OpenSSL library. The only thing we can do we already have done
2567
     * by choosing our own callback certificate verification.
2568
     *
2569
     * Error handling:
2570
     * If the SSL handhake fails, we print out an error message and remove
2571
     * everything that might be there. A session has to be removed anyway,
2572
     * because RFC2246 requires it. 
2573
     */
2574
    sts = do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
2575
			   SSL_connect, NULL, NULL, NULL, 0);
2576
    if (sts <= 0) {
2577
	msg_info("SSL_connect error to %s: %d", peername, sts);
2578
	pfixtls_print_errors();
2579
	session = SSL_get_session(TLScontext->con);
2580
	if (session) {
2581
	    SSL_CTX_remove_session(ctx, session);
2582
	    if (var_smtp_tls_loglevel >= 2)
2583
		msg_info("SSL session removed");
2584
	}
2585
	if ((old_session) && (!SSL_session_reused(TLScontext->con)))
2586
	    SSL_SESSION_free(old_session);	/* Must also be removed */
2587
	SSL_free(TLScontext->con);
2588
	myfree((char *)TLScontext);
2589
	return (-1);
2590
    }
2591
2592
    if (!SSL_session_reused(TLScontext->con)) {
2593
	SSL_SESSION_free(old_session);	/* Remove unused session */
2594
    }
2595
    else if (var_smtp_tls_loglevel >= 3)
2596
	msg_info("Reusing old session");
2597
2598
    /* Only loglevel==4 dumps everything */
2599
    if (var_smtp_tls_loglevel < 4)
2600
	do_dump = 0;
2601
2602
    /*
2603
     * Lets see, whether a peer certificate is available and what is
2604
     * the actual information. We want to save it for later use.
2605
     */
2606
    peer = SSL_get_peer_certificate(TLScontext->con);
2607
    if (peer != NULL) {
2608
	if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
2609
	    tls_info->peer_verified = 1;
2610
2611
	TLScontext->peer_CN[0] = '\0';
2612
	if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
2613
			NID_commonName, TLScontext->peer_CN, CCERT_BUFSIZ)) {
2614
	    msg_info("Could not parse server's subject CN");
2615
	    pfixtls_print_errors();
2616
	}
2617
	tls_info->peer_CN = TLScontext->peer_CN;
2618
2619
	TLScontext->issuer_CN[0] = '\0';
2620
	if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
2621
			NID_commonName, TLScontext->issuer_CN, CCERT_BUFSIZ)) {
2622
	    msg_info("Could not parse server's issuer CN");
2623
	    pfixtls_print_errors();
2624
	}
2625
	if (!TLScontext->issuer_CN[0]) {
2626
	    /* No issuer CN field, use Organization instead */
2627
	    if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
2628
		NID_organizationName, TLScontext->issuer_CN, CCERT_BUFSIZ)) {
2629
		msg_info("Could not parse server's issuer Organization");
2630
		pfixtls_print_errors();
2631
	    }
2632
	}
2633
	tls_info->issuer_CN = TLScontext->issuer_CN;
2634
2635
	if (var_smtp_tls_loglevel >= 1) {
2636
	    if (tls_info->peer_verified)
2637
		msg_info("Verified: subject_CN=%s, issuer=%s",
2638
			 TLScontext->peer_CN, TLScontext->issuer_CN);
2639
	    else
2640
		msg_info("Unverified: subject_CN=%s, issuer=%s",
2641
			 TLScontext->peer_CN, TLScontext->issuer_CN);
2642
	}
2643
	X509_free(peer);
2644
    }
2645
2646
    /*
2647
     * Finally, collect information about protocol and cipher for logging
2648
     */ 
2649
    tls_info->protocol = SSL_get_version(TLScontext->con);
2650
    cipher = SSL_get_current_cipher(TLScontext->con);
2651
    tls_info->cipher_name = SSL_CIPHER_get_name(cipher);
2652
    tls_info->cipher_usebits = SSL_CIPHER_get_bits(cipher,
2653
						 &(tls_info->cipher_algbits));
2654
2655
    pfixtls_clientactive = 1;
2656
2657
    /*
2658
     * The TLS engine is active, switch to the pfixtls_timed_read/write()
2659
     * functions.
2660
     */
2661
    vstream_control(stream,
2662
		    VSTREAM_CTL_READ_FN, pfixtls_timed_read,
2663
		    VSTREAM_CTL_WRITE_FN, pfixtls_timed_write,
2664
		    VSTREAM_CTL_CONTEXT, (void *)TLScontext,
2665
		    VSTREAM_CTL_END);
2666
2667
    msg_info("TLS connection established to %s: %s with cipher %s (%d/%d bits)",
2668
	     peername,
2669
	     tls_info->protocol, tls_info->cipher_name,
2670
	     tls_info->cipher_usebits, tls_info->cipher_algbits);
2671
2672
    pfixtls_stir_seed();
2673
2674
    return (0);
2675
}
2676
2677
 /*
2678
  * Shut down the TLS connection, that does mean: remove all the information
2679
  * and reset the flags! This is needed if the actual running smtp is to
2680
  * be restarted. We do not give back any value, as there is nothing to
2681
  * be reported.
2682
  * Since our session cache is external, we will remove the session from
2683
  * memory in any case. The SSL_CTX_flush_sessions might be redundant here,
2684
  * I however want to make sure nothing is left.
2685
  * RFC2246 requires us to remove sessions if something went wrong, as
2686
  * indicated by the "failure" value,so we remove it from the external
2687
  * cache, too.
2688
  */
2689
int     pfixtls_stop_clienttls(VSTREAM *stream, int timeout, int failure,
2690
			       tls_info_t *tls_info)
2691
{
2692
    TLScontext_t *TLScontext;
2693
    int retval;
2694
2695
    if (pfixtls_clientactive) {
2696
	TLScontext = (TLScontext_t *)vstream_context(stream);
2697
	/*
2698
	 * Perform SSL_shutdown() twice, as the first attempt may return
2699
	 * to early: it will only send out the shutdown alert but it will
2700
	 * not wait for the peer's shutdown alert. Therefore, when we are
2701
	 * the first party to send the alert, we must call SSL_shutdown()
2702
	 * again.
2703
	 * On failure we don't want to resume the session, so we will not
2704
	 * perform SSL_shutdown() and the session will be removed as being
2705
	 * bad.
2706
	 */
2707
	if (!failure) {
2708
	    retval = do_tls_operation(vstream_fileno(stream), timeout,
2709
				TLScontext, SSL_shutdown, NULL, NULL, NULL, 0);
2710
	    if (retval == 0)
2711
		do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
2712
				SSL_shutdown, NULL, NULL, NULL, 0);
2713
	}
2714
	/*
2715
	 * Free the SSL structure and the BIOs. Warning: the internal_bio is
2716
	 * connected to the SSL structure and is automatically freed with
2717
	 * it. Do not free it again (core dump)!!
2718
	 * Only free the network_bio.
2719
	 */
2720
	SSL_free(TLScontext->con);
2721
	BIO_free(TLScontext->network_bio);
2722
	myfree((char *)TLScontext);
2723
	vstream_control(stream,
2724
		    VSTREAM_CTL_READ_FN, (VSTREAM_FN) NULL,
2725
		    VSTREAM_CTL_WRITE_FN, (VSTREAM_FN) NULL,
2726
		    VSTREAM_CTL_CONTEXT, (void *) NULL,
2727
		    VSTREAM_CTL_END);
2728
	SSL_CTX_flush_sessions(ctx, time(NULL));
2729
2730
	pfixtls_stir_seed();
2731
	pfixtls_exchange_seed();
2732
2733
	*tls_info = tls_info_zero;
2734
	pfixtls_clientactive = 0;
2735
2736
    }
2737
2738
    return (0);
2739
}
2740
2741
2742
#endif /* HAS_SSL */
(-)postfix-1.1.11-20020613-orig/src/global/pfixtls.h (+76 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*      pfixtls 3h
4
/* SUMMARY
5
/*      TLS routines
6
/* SYNOPSIS
7
/*      include "pfixtls.h"
8
/* DESCRIPTION
9
/* .nf
10
/*--*/
11
12
#ifndef PFIXTLS_H_INCLUDED
13
#define PFIXTLS_H_INCLUDED
14
15
typedef struct {
16
    int     peer_verified;
17
    char   *peer_subject;
18
    char   *peer_issuer;
19
    char   *peer_fingerprint;
20
    char   *peer_CN;
21
    char   *issuer_CN;
22
    const char *protocol;
23
    const char *cipher_name;
24
    int     cipher_usebits;
25
    int     cipher_algbits;
26
} tls_info_t;
27
28
extern const tls_info_t tls_info_zero;
29
30
#ifdef HAS_SSL
31
32
typedef struct {
33
    long scache_db_version;
34
    long openssl_version;
35
    time_t timestamp;		/* We could add other info here... */
36
    int enforce_peername;
37
} pfixtls_scache_info_t;
38
39
extern const long scache_db_version;
40
extern const long openssl_version;
41
42
int     pfixtls_timed_read(int fd, void *buf, unsigned len, int timout,
43
			   void *unused_timeout);
44
int     pfixtls_timed_write(int fd, void *buf, unsigned len, int timeout,
45
			    void *unused_timeout);
46
47
extern int pfixtls_serverengine;
48
int     pfixtls_init_serverengine(int verifydepth, int askcert);
49
int     pfixtls_start_servertls(VSTREAM *stream, int timeout,
50
				const char *peername, const char *peeraddr,
51
				tls_info_t *tls_info, int require_cert);
52
int     pfixtls_stop_servertls(VSTREAM *stream, int timeout, int failure,
53
			       tls_info_t *tls_info);
54
55
extern int pfixtls_clientengine;
56
int     pfixtls_init_clientengine(int verifydepth);
57
int     pfixtls_start_clienttls(VSTREAM *stream, int timeout,
58
				int enforce_peername,
59
				const char *peername,
60
				tls_info_t *tls_info);
61
int     pfixtls_stop_clienttls(VSTREAM *stream, int timeout, int failure,
62
			       tls_info_t *tls_info);
63
64
#endif /* PFIXTLS_H_INCLUDED */
65
#endif
66
67
/* LICENSE
68
/* .ad
69
/* .fi
70
/* AUTHOR(S)
71
/*	Lutz Jaenicke
72
/*	BTU Cottbus
73
/*	Allgemeine Elektrotechnik
74
/*	Universitaetsplatz 3-4
75
/*	D-03044 Cottbus, Germany
76
/*--*/
(-)postfix-1.1.11-20020613-orig/src/global/resolve_local.c (+22 lines)
Lines 42-47 Link Here
42
#include <netinet/in.h>
42
#include <netinet/in.h>
43
#include <arpa/inet.h>
43
#include <arpa/inet.h>
44
#include <string.h>
44
#include <string.h>
45
#include <netdb.h>
45
46
46
#ifndef INADDR_NONE
47
#ifndef INADDR_NONE
47
#define INADDR_NONE 0xffffffff
48
#define INADDR_NONE 0xffffffff
Lines 79-85 Link Here
79
{
80
{
80
    char   *saved_addr = mystrdup(addr);
81
    char   *saved_addr = mystrdup(addr);
81
    char   *dest;
82
    char   *dest;
83
#ifdef INET6
84
    struct addrinfo hints, *res, *res0;
85
    int error;
86
#else
82
    struct in_addr ipaddr;
87
    struct in_addr ipaddr;
88
#endif
83
    int     len;
89
    int     len;
84
90
85
#define RETURN(x) { myfree(saved_addr); return(x); }
91
#define RETURN(x) { myfree(saved_addr); return(x); }
Lines 111-119 Link Here
111
    if (*dest == '[' && dest[len - 1] == ']') {
117
    if (*dest == '[' && dest[len - 1] == ']') {
112
	dest++;
118
	dest++;
113
	dest[len -= 2] = 0;
119
	dest[len -= 2] = 0;
120
#ifdef INET6
121
	memset(&hints, 0, sizeof(hints));
122
	hints.ai_family = PF_UNSPEC;
123
	hints.ai_socktype = SOCK_DGRAM;
124
	error = getaddrinfo(dest, NULL, &hints, &res0);
125
	if (!error) {
126
	    for (res = res0; res; res = res->ai_next) {
127
		if (own_inet_addr(res->ai_addr)) {
128
		    freeaddrinfo(res0);
129
		    RETURN(1);
130
		}
131
	    }
132
	    freeaddrinfo(res0);
133
	}
134
#else
114
	if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
135
	if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
115
	    && own_inet_addr(&ipaddr))
136
	    && own_inet_addr(&ipaddr))
116
	    RETURN(1);
137
	    RETURN(1);
138
#endif
117
    }
139
    }
118
140
119
    /*
141
    /*
(-)postfix-1.1.11-20020613-orig/src/global/wildcard_inet_addr.c (+82 lines)
Line 0 Link Here
1
/* System library. */
2
3
#include <sys_defs.h>
4
#include <netinet/in.h>
5
#include <arpa/inet.h>
6
#include <string.h>
7
#ifdef INET6
8
#include <sys/socket.h>
9
#endif
10
#include <netdb.h>
11
12
#ifdef STRCASECMP_IN_STRINGS_H
13
#include <strings.h>
14
#endif
15
16
/* Utility library. */
17
18
#include <msg.h>
19
#include <mymalloc.h>
20
#include <inet_addr_list.h>
21
#include <inet_addr_local.h>
22
#include <inet_addr_host.h>
23
#include <stringops.h>
24
25
/* Global library. */
26
27
#include <mail_params.h>
28
#include <wildcard_inet_addr.h>
29
30
/* Application-specific. */
31
static INET_ADDR_LIST addr_list;
32
33
/* wildcard_inet_addr_init - initialize my own address list */
34
35
static void wildcard_inet_addr_init(INET_ADDR_LIST *addr_list)
36
{
37
#ifdef INET6
38
    struct addrinfo hints, *res, *res0;
39
    char hbuf[NI_MAXHOST];
40
    int error;
41
#ifdef NI_WITHSCOPEID
42
    const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
43
#else
44
    const int niflags = NI_NUMERICHOST;
45
#endif
46
47
    inet_addr_list_init(addr_list);
48
49
    memset(&hints, 0, sizeof(hints));
50
    hints.ai_family = PF_UNSPEC;
51
    hints.ai_socktype = SOCK_STREAM;
52
    hints.ai_flags = AI_PASSIVE;
53
    error = getaddrinfo(NULL, "0", &hints, &res0);
54
    if (error)
55
	msg_fatal("could not get list of wildcard addresses");
56
    for (res = res0; res; res = res->ai_next) {
57
	if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
58
	    continue;
59
	if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
60
	    NULL, 0, niflags) != 0)
61
	    continue;
62
	if (inet_addr_host(addr_list, hbuf) == 0)
63
	    continue; /* msg_fatal("config variable %s: host not found: %s",
64
		      VAR_INET_INTERFACES, hbuf); */
65
    }
66
    freeaddrinfo(res0);
67
#else
68
    if (inet_addr_host(addr_list, "0.0.0.0") == 0)
69
	msg_fatal("config variable %s: host not found: %s",
70
		  VAR_INET_INTERFACES, "0.0.0.0");
71
#endif
72
}
73
74
/* wildcard_inet_addr_list - return list of addresses */
75
76
INET_ADDR_LIST *wildcard_inet_addr_list(void)
77
{
78
    if (addr_list.used == 0)
79
	wildcard_inet_addr_init(&addr_list);
80
81
    return (&addr_list);
82
}
(-)postfix-1.1.11-20020613-orig/src/global/wildcard_inet_addr.h (+36 lines)
Line 0 Link Here
1
#ifndef _WILDCARD_INET_ADDR_H_INCLUDED_
2
#define _WILDCARD_INET_ADDR_H_INCLUDED_
3
4
/*++
5
/* NAME
6
/*	wildcard_inet_addr_list 3h
7
/* SUMMARY
8
/*	grab the list of wildcard IP addresses.
9
/* SYNOPSIS
10
/*	#include <own_inet_addr.h>
11
/* DESCRIPTION
12
/* .nf
13
/*--*/
14
15
 /*
16
  * System library.
17
  */
18
#include <netinet/in.h>
19
#ifdef INET6
20
#include <sys/socket.h>
21
#endif
22
23
 /*
24
  * External interface.
25
  */
26
extern struct INET_ADDR_LIST *wildcard_inet_addr_list(void);
27
28
/* LICENSE
29
/* .ad
30
/* .fi
31
/*	foo
32
/* AUTHOR(S)
33
/*	Jun-ichiro itojun Hagino
34
/*--*/
35
36
#endif
(-)postfix-1.1.11-20020613-orig/src/lmtp/lmtp.c (+12 lines)
Lines 190-195 Link Here
190
/* .IP \fBlmtp_quit_timeout\fR
190
/* .IP \fBlmtp_quit_timeout\fR
191
/*	Timeout for sending the \fBQUIT\fR command, and for
191
/*	Timeout for sending the \fBQUIT\fR command, and for
192
/*	receiving the server response.
192
/*	receiving the server response.
193
/* .IP \fBlmtp_bind_address\fR
194
/*	Numerical source network address (IPv4) to bind to when making
195
/*	a connection.
196
/* .IP \fBlmtp_bind_address6\fR
197
/*	Numerical source network address (IPv6) to bind to when making
198
/*	a connection.
193
/* SEE ALSO
199
/* SEE ALSO
194
/*	bounce(8) non-delivery status reports
200
/*	bounce(8) non-delivery status reports
195
/*	local(8) local mail delivery
201
/*	local(8) local mail delivery
Lines 276-281 Link Here
276
char   *var_lmtp_sasl_opts;
282
char   *var_lmtp_sasl_opts;
277
char   *var_lmtp_sasl_passwd;
283
char   *var_lmtp_sasl_passwd;
278
bool    var_lmtp_sasl_enable;
284
bool    var_lmtp_sasl_enable;
285
char   *var_lmtp_bind_addr;
286
char   *var_lmtp_bind_addr6;
279
287
280
 /*
288
 /*
281
  * Global variables.
289
  * Global variables.
Lines 514-519 Link Here
514
	VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
522
	VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
515
	VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_lmtp_sasl_passwd, 0, 0,
523
	VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_lmtp_sasl_passwd, 0, 0,
516
	VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_lmtp_sasl_opts, 0, 0,
524
	VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_lmtp_sasl_opts, 0, 0,
525
	VAR_LMTP_BIND_ADDR, DEF_LMTP_BIND_ADDR, &var_lmtp_bind_addr, 0, 0,
526
#ifdef INET6
527
	VAR_LMTP_BIND_ADDR6, DEF_LMTP_BIND_ADDR6, &var_lmtp_bind_addr6, 0, 0,
528
#endif
517
	0,
529
	0,
518
    };
530
    };
519
    static CONFIG_INT_TABLE int_table[] = {
531
    static CONFIG_INT_TABLE int_table[] = {
(-)postfix-1.1.11-20020613-orig/src/lmtp/lmtp_connect.c (-12 / +186 lines)
Lines 92-102 Link Here
92
#include <iostuff.h>
92
#include <iostuff.h>
93
#include <timed_connect.h>
93
#include <timed_connect.h>
94
#include <stringops.h>
94
#include <stringops.h>
95
#include <inet_addr_list.h>
95
96
96
/* Global library. */
97
/* Global library. */
97
98
98
#include <mail_params.h>
99
#include <mail_params.h>
99
#include <mail_proto.h>
100
#include <mail_proto.h>
101
#include <own_inet_addr.h>
100
102
101
/* DNS library. */
103
/* DNS library. */
102
104
Lines 166-178 Link Here
166
			              const char *destination, VSTRING *why)
168
			              const char *destination, VSTRING *why)
167
{
169
{
168
    char   *myname = "lmtp_connect_addr";
170
    char   *myname = "lmtp_connect_addr";
169
    struct sockaddr_in sin;
171
#ifdef INET6
170
    int     sock;
172
    struct sockaddr_storage ss;
173
#else
174
    struct sockaddr ss;
175
#endif
176
    struct sockaddr *sa;
177
    struct sockaddr_in *sin;
178
#ifdef INET6
179
    struct sockaddr_in6 *sin6;
180
#endif
181
    SOCKADDR_SIZE salen;
182
#ifdef INET6
183
    char hbuf[NI_MAXHOST];
184
#else
185
    char hbuf[sizeof("255.255.255.255") + 1];
186
#endif
187
    int     sock = -1;
188
    INET_ADDR_LIST *addr_list;
189
    char   *bind_addr;
190
191
    sa = (struct sockaddr *)&ss;
192
    sin = (struct sockaddr_in *)&ss;
193
#ifdef INET6
194
    sin6 = (struct sockaddr_in6 *)&ss;
195
#endif
171
196
172
    /*
197
    /*
173
     * Sanity checks.
198
     * Sanity checks.
174
     */
199
     */
175
    if (addr->data_len > sizeof(sin.sin_addr)) {
200
#ifdef INET6
201
    if (((addr->type==T_A) && (addr->data_len > sizeof(sin->sin_addr))) ||
202
	((addr->type==T_AAAA) && (addr->data_len > sizeof(sin6->sin6_addr))))
203
#else
204
    if (addr->data_len > sizeof(sin->sin_addr))
205
#endif
206
    {
176
	msg_warn("%s: skip address with length %d", myname, addr->data_len);
207
	msg_warn("%s: skip address with length %d", myname, addr->data_len);
177
	lmtp_errno = LMTP_RETRY;
208
	lmtp_errno = LMTP_RETRY;
178
	return (0);
209
	return (0);
Lines 181-205 Link Here
181
    /*
212
    /*
182
     * Initialize.
213
     * Initialize.
183
     */
214
     */
184
    memset((char *) &sin, 0, sizeof(sin));
215
    switch (addr->type) {
185
    sin.sin_family = AF_INET;
216
#ifdef INET6
217
    case T_AAAA:
218
	bind_addr = var_lmtp_bind_addr6;
219
	memset(sin6, 0, sizeof(*sin6));
220
	sin6->sin6_family = AF_INET6;
221
	salen = sizeof(*sin6);
222
	break;
223
#endif
224
    default: /* T_A: */
225
	bind_addr = var_lmtp_bind_addr;
226
	memset(sin, 0, sizeof(*sin));
227
	sin->sin_family = AF_INET;
228
	salen = sizeof(*sin);
229
	break;
230
    };
231
#ifdef HAS_SALEN
232
    sa->sa_len = salen;
233
#endif
186
234
187
    if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
235
    if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
188
	msg_fatal("%s: socket: %m", myname);
236
	msg_fatal("%s: socket: %m", myname);
189
237
190
    /*
238
    /*
239
     * Allow the sysadmin to specify the source address
240
     */
241
242
    if (*bind_addr) {
243
#ifndef INET6
244
	struct sockaddr_in sin;
245
246
	memset(&sin, 0, sizeof(sin));
247
	sin.sin_family = AF_INET;
248
#ifdef HAS_SA_LEN
249
	sin.sin_len = sizeof(sin);
250
#endif
251
	sin.sin_addr.s_addr = inet_addr(bind_addr);
252
	if (sin.sin_addr.s_addr == INADDR_NONE)
253
	    msg_fatal("%s: bad %s parameter: %s",
254
		      myname, VAR_LMTP_BIND_ADDR, var_smtp_bind_addr);
255
	if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0)
256
	    msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
257
	if (msg_verbose)
258
	    msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
259
#else
260
	char hbufl[NI_MAXHOST];
261
	struct addrinfo hints, *res;
262
263
	memset(&hints, 0, sizeof(hints));
264
	hints.ai_family = sa->sa_family;
265
	hints.ai_socktype = SOCK_STREAM;
266
	hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
267
	snprintf(hbufl, sizeof(hbufl)-1, "%s", bind_addr);
268
	if (getaddrinfo(hbufl, NULL, &hints, &res) == 0) {
269
	    (void)getnameinfo(res->ai_addr, res->ai_addrlen, hbufl,
270
		sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
271
	    if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
272
		msg_warn("%s: bind %s: %m", myname, hbufl);
273
	    freeaddrinfo(res);
274
	    if (msg_verbose)
275
		msg_info("%s: bind %s", myname, hbufl);
276
	}
277
#endif
278
    }
279
280
    /*
281
     * If running on a virtual host, start connections from the
282
     * right address.
283
     */
284
285
    else if ((addr_list = own_inet_addr_list())->used == 1) {
286
#ifndef INET6
287
	struct sockaddr_in sin;
288
	unsigned long inaddr; /* XXX BAD!*/
289
290
	memset(&sin, 0, sizeof(sin));
291
	sin.sin_family = AF_INET;
292
#ifdef HAS_SA_LEN
293
	sin.sin_len = sizeof(sin);
294
#endif
295
	memcpy((char *)&sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
296
	inaddr = (unsigned long)ntohl(sin.sin_addr.s_addr);
297
	if (!IN_CLASSA(inaddr)
298
	    /* XXX Are the two following lines correct? */
299
	    || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) ==
300
	    IN_LOOPBACKNET)) {
301
	    if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
302
		msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
303
	    if (msg_verbose)
304
		msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
305
	}
306
#else
307
	char hbufl[NI_MAXHOST];
308
	struct addrinfo hints, *res = NULL, *loopback = NULL;
309
310
	memset(&hints, 0, sizeof(hints));
311
	hints.ai_family = sa->sa_family;
312
	hints.ai_socktype = SOCK_STREAM;
313
	if (getaddrinfo(NULL, "0", &hints, &loopback) != 0)
314
	    loopback = NULL;
315
316
	/*
317
	 * getnameinfo -> getaddrinfo loop is here so that we can
318
	 * get rid of port
319
	 */
320
	(void)getnameinfo((struct sockaddr *)addr_list->addrs,
321
	    SA_LEN((struct sockaddr *)addr_list->addrs),
322
	    hbufl, sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
323
	hbufl[sizeof(hbufl) - 1] = 0;
324
	memset(&hints, 0, sizeof(hints));
325
	hints.ai_family = sa->sa_family;
326
	hints.ai_socktype = SOCK_STREAM;
327
	hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
328
	if (getaddrinfo(hbufl, NULL, &hints, &res) == 0 &&
329
	    !(res->ai_addrlen == loopback->ai_addrlen &&
330
	    memcmp(res->ai_addr, loopback->ai_addr, res->ai_addrlen) == 0)) {
331
	    if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
332
		msg_warn("%s: bind %s: %m", myname, hbufl);
333
	    if (msg_verbose)
334
		msg_info("%s: bind %s", myname, hbufl);
335
	}
336
	if (res)
337
	    freeaddrinfo(res);
338
	if (loopback)
339
	    freeaddrinfo(loopback);
340
#endif
341
    }
342
343
    /*
191
     * Connect to the LMTP server.
344
     * Connect to the LMTP server.
192
     */
345
     */
193
    sin.sin_port = port;
346
    switch (addr->type) {
194
    memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
347
#ifdef INET6
348
    case T_AAAA:
349
	/* XXX scope-unfriendly */
350
	memset(sin6, 0, sizeof(*sin6));
351
	sin6->sin6_port = port;
352
	sin6->sin6_family = AF_INET6;
353
	salen = sizeof(*sin6);
354
	memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
355
	inet_ntop(AF_INET6, &sin6->sin6_addr, hbuf, sizeof(hbuf));
356
	break;
357
#endif
358
    default: /* T_A: */
359
	memset(sin, 0, sizeof(*sin));
360
	sin->sin_port = port;
361
	sin->sin_family = AF_INET;
362
	salen = sizeof(*sin6);
363
	memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
364
	inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
365
	break;
366
    }
367
#ifdef HAS_SA_LEN
368
    sa->sa_len = salen;
369
#endif
195
370
196
    if (msg_verbose)
371
    if (msg_verbose)
197
	msg_info("%s: trying: %s[%s] port %d...",
372
	msg_info("%s: trying: %s[%s] port %d...",
198
		 myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
373
		 myname, addr->name, hbuf, ntohs(port));
199
374
200
    return (lmtp_connect_sock(sock, (struct sockaddr *) & sin, sizeof(sin),
375
    return (lmtp_connect_sock(sock, (struct sockaddr *)sa, salen,
201
			      addr->name, inet_ntoa(sin.sin_addr),
376
			      addr->name, hbuf, destination, why));
202
			      destination, why));
203
}
377
}
204
378
205
/* lmtp_connect_sock - connect a socket over some transport */
379
/* lmtp_connect_sock - connect a socket over some transport */
(-)postfix-1.1.11-20020613-orig/src/master/master_ent.c (+5 lines)
Lines 284-291 Link Here
284
	    inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
284
	    inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
285
	    serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
285
	    serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
286
	} else if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) {
286
	} else if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) {
287
#ifdef INET6
288
		MASTER_INET_ADDRLIST(serv) = wildcard_inet_addr_list();
289
		serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
290
#else
287
	    MASTER_INET_ADDRLIST(serv) = 0;	/* wild-card */
291
	    MASTER_INET_ADDRLIST(serv) = 0;	/* wild-card */
288
	    serv->listen_fd_count = 1;
292
	    serv->listen_fd_count = 1;
293
#endif
289
	} else {
294
	} else {
290
	    MASTER_INET_ADDRLIST(serv) = own_inet_addr_list();	/* virtual */
295
	    MASTER_INET_ADDRLIST(serv) = own_inet_addr_list();	/* virtual */
291
	    serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
296
	    serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
(-)postfix-1.1.11-20020613-orig/src/master/master_listen.c (-6 / +28 lines)
Lines 64-76 Link Here
64
64
65
#include "master.h"
65
#include "master.h"
66
66
67
#ifdef INET6
68
#include <netdb.h>
69
#include <stdio.h>
70
#endif 
71
67
/* master_listen_init - enable connection requests */
72
/* master_listen_init - enable connection requests */
68
73
69
void    master_listen_init(MASTER_SERV *serv)
74
void    master_listen_init(MASTER_SERV *serv)
70
{
75
{
71
    char   *myname = "master_listen_init";
76
    char   *myname = "master_listen_init";
72
    char   *end_point;
77
    char   *end_point;
73
    int     n;
78
    int     n,m,tmpfd;
79
#ifdef INET6
80
    char hbuf[NI_MAXHOST];
81
    SOCKADDR_SIZE salen;
82
#endif
74
83
75
    /*
84
    /*
76
     * Find out what transport we should use, then create one or more
85
     * Find out what transport we should use, then create one or more
Lines 111-128 Link Here
111
	    serv->listen_fd[0] =
120
	    serv->listen_fd[0] =
112
		inet_listen(MASTER_INET_PORT(serv),
121
		inet_listen(MASTER_INET_PORT(serv),
113
			    serv->max_proc > var_proc_limit ?
122
			    serv->max_proc > var_proc_limit ?
114
			    serv->max_proc : var_proc_limit, NON_BLOCKING);
123
			    serv->max_proc : var_proc_limit, NON_BLOCKING, 1);
115
	    close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
124
	    close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
116
	} else {				/* virtual or host:port */
125
	} else {				/* virtual or host:port */
117
	    for (n = 0; n < serv->listen_fd_count; n++) {
126
	    for (m = n = 0; n < serv->listen_fd_count; n++) {
127
#ifdef INET6
128
		if (getnameinfo((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n],
129
			SA_LEN((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n]), 
130
			hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) {
131
		    strncpy(hbuf, "?????", sizeof(hbuf));
132
		}
133
		end_point = concatenate(hbuf, ":", MASTER_INET_PORT(serv), (char *) 0);
134
#else
118
		end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
135
		end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
119
				   ":", MASTER_INET_PORT(serv), (char *) 0);
136
				   ":", MASTER_INET_PORT(serv), (char *) 0);
120
		serv->listen_fd[n]
137
#endif
138
		tmpfd
121
		    = inet_listen(end_point, serv->max_proc > var_proc_limit ?
139
		    = inet_listen(end_point, serv->max_proc > var_proc_limit ?
122
			     serv->max_proc : var_proc_limit, NON_BLOCKING);
140
			     serv->max_proc : var_proc_limit, NON_BLOCKING, 0);
123
		close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC);
141
		if (tmpfd >= 0) {
142
		    serv->listen_fd[m] = tmpfd;
143
		    close_on_exec(serv->listen_fd[m++], CLOSE_ON_EXEC);
144
		}
124
		myfree(end_point);
145
		myfree(end_point);
125
	    }
146
	    }
147
	    serv->listen_fd_count=m;
126
	}
148
	}
127
	break;
149
	break;
128
    default:
150
    default:
(-)postfix-1.1.11-20020613-orig/src/qmgr/qmgr_message.c (+4 lines)
Lines 507-513 Link Here
507
	 * every front-ent program.
507
	 * every front-ent program.
508
	 */
508
	 */
509
	if ((at = strrchr(recipient->address, '@')) != 0
509
	if ((at = strrchr(recipient->address, '@')) != 0
510
#ifdef INET6
511
	    && (at + 1)[strspn(at + 1, "[]0123456789.:abcdef")] != 0
512
#else
510
	    && (at + 1)[strspn(at + 1, "[]0123456789.")] != 0
513
	    && (at + 1)[strspn(at + 1, "[]0123456789.")] != 0
514
#endif
511
	    && valid_hostname(at + 1, DONT_GRIPE) == 0) {
515
	    && valid_hostname(at + 1, DONT_GRIPE) == 0) {
512
	    qmgr_bounce_recipient(message, recipient,
516
	    qmgr_bounce_recipient(message, recipient,
513
				  "bad host/domain syntax: \"%s\"", at + 1);
517
				  "bad host/domain syntax: \"%s\"", at + 1);
(-)postfix-1.1.11-20020613-orig/src/qmqpd/qmqpd_peer.c (-17 / +77 lines)
Lines 70-75 Link Here
70
    )
70
    )
71
#endif
71
#endif
72
72
73
#ifdef INET6
74
#define GAI_STRERROR(error) \
75
	((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
76
#endif
77
73
/* Utility library. */
78
/* Utility library. */
74
79
75
#include <msg.h>
80
#include <msg.h>
Lines 79-85 Link Here
79
84
80
/* Global library. */
85
/* Global library. */
81
86
82
83
/* Application-specific. */
87
/* Application-specific. */
84
88
85
#include "qmqpd.h"
89
#include "qmqpd.h"
Lines 88-103 Link Here
88
92
89
void    qmqpd_peer_init(QMQPD_STATE *state)
93
void    qmqpd_peer_init(QMQPD_STATE *state)
90
{
94
{
91
    struct sockaddr_in sin;
95
#ifdef INET6
92
    SOCKADDR_SIZE len = sizeof(sin);
96
    struct sockaddr_storage ss;
97
#else
98
    struct sockaddr ss;
99
    struct in_addr *in;
93
    struct hostent *hp;
100
    struct hostent *hp;
94
    int     i;
101
#endif
102
    struct sockaddr *sa;
103
    SOCKADDR_SIZE len;
104
105
    sa = (struct sockaddr *)&ss;
106
    len = sizeof(ss);
95
107
96
    /*
108
    /*
97
     * Look up the peer address information.
109
     * Look up the peer address information.
98
     */
110
     */
99
    if (getpeername(vstream_fileno(state->client),
111
    if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) {
100
		    (struct sockaddr *) & sin, &len) >= 0) {
101
	errno = 0;
112
	errno = 0;
102
    }
113
    }
103
114
Lines 112-127 Link Here
112
    /*
123
    /*
113
     * Look up and "verify" the client hostname.
124
     * Look up and "verify" the client hostname.
114
     */
125
     */
115
    else if (errno == 0 && sin.sin_family == AF_INET) {
126
    else if (errno == 0 && (sa->sa_family == AF_INET
116
	state->addr = mystrdup(inet_ntoa(sin.sin_addr));
127
#ifdef INET6
117
	hp = gethostbyaddr((char *) &(sin.sin_addr),
128
	     || sa->sa_family == AF_INET6
118
			   sizeof(sin.sin_addr), AF_INET);
129
#endif
119
	if (hp == 0) {
130
             )) {
131
#ifdef INET6
132
	char hbuf[NI_MAXHOST];
133
	char abuf[NI_MAXHOST];
134
	struct addrinfo hints, *rnull = NULL;
135
#else
136
	char abuf[sizeof("255.255.255.255") + 1];
137
	char *hbuf;
138
#endif
139
	int error = -1;
140
141
#ifdef INET6
142
	(void)getnameinfo(sa, len, abuf, sizeof(abuf), NULL, 0,
143
			  NI_NUMERICHOST);
144
#else
145
	in = &((struct sockaddr_in *)sa)->sin_addr;
146
	inet_ntop(AF_INET, in, abuf, sizeof(abuf));
147
#endif
148
149
	state->addr = mystrdup(abuf);
150
#ifdef INET6
151
	error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0,
152
			    NI_NAMEREQD);
153
#else
154
	hbuf = NULL;
155
	hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET);
156
	if (hp) {
157
	    error = 0;
158
	    hbuf = mystrdup(hp->h_name);
159
	    state->name = mystrdup("unknown");
160
	} else {
161
	    error = 1;
162
	}
163
#endif
164
	if (error) {
120
	    state->name = mystrdup("unknown");
165
	    state->name = mystrdup("unknown");
121
	} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
166
	} else if (!valid_hostname(hbuf, DONT_GRIPE)) {
122
	    state->name = mystrdup("unknown");
167
	    state->name = mystrdup("unknown");
123
	} else {
168
	} else {
124
	    state->name = mystrdup(hp->h_name);	/* hp->name is clobbered!! */
169
	    state->name = mystrdup(hbuf);	/* hp->name is clobbered!! */
125
170
126
	    /*
171
	    /*
127
	     * Reject the hostname if it does not list the peer address.
172
	     * Reject the hostname if it does not list the peer address.
Lines 131-146 Link Here
131
	state->name = mystrdup("unknown"); \
176
	state->name = mystrdup("unknown"); \
132
    }
177
    }
133
178
179
#ifdef INET6
180
	    memset(&hints, 0, sizeof(hints));
181
	    hints.ai_family = AF_UNSPEC;
182
	    hints.ai_socktype = SOCK_STREAM;
183
	    error = getaddrinfo(state->name, NULL, &hints, &rnull);
184
	    if (error) {
185
		msg_warn("%s: hostname %s verification failed: %s",
186
		         state->addr, state->name, GAI_STRERROR(error));
187
		REJECT_PEER_NAME(state);
188
	    }
189
	    /* memcmp() isn't needed if we use getaddrinfo */
190
	    if (rnull)
191
		freeaddrinfo(rnull);
192
#else
134
	    hp = gethostbyname(state->name);	/* clobbers hp->name!! */
193
	    hp = gethostbyname(state->name);	/* clobbers hp->name!! */
135
	    if (hp == 0) {
194
	    if (hp == 0) {
136
		msg_warn("%s: hostname %s verification failed: %s",
195
		msg_warn("%s: hostname %s verification failed: %s",
137
			 state->addr, state->name, HSTRERROR(h_errno));
196
			 state->addr, state->name, HSTRERROR(h_errno));
138
		REJECT_PEER_NAME(state);
197
		REJECT_PEER_NAME(state);
139
	    } else if (hp->h_length != sizeof(sin.sin_addr)) {
198
	    } else if (hp->h_length != sizeof(*in)) {
140
		msg_warn("%s: hostname %s verification failed: bad address size %d",
199
		msg_warn("%s: hostname %s verification failed: bad address size %d",
141
			 state->addr, state->name, hp->h_length);
200
			 state->addr, state->name, hp->h_length);
142
		REJECT_PEER_NAME(state);
201
		REJECT_PEER_NAME(state);
143
	    } else {
202
	    } else {
203
		int i;
144
		for (i = 0; /* void */ ; i++) {
204
		for (i = 0; /* void */ ; i++) {
145
		    if (hp->h_addr_list[i] == 0) {
205
		    if (hp->h_addr_list[i] == 0) {
146
			msg_warn("%s: address not listed for hostname %s",
206
			msg_warn("%s: address not listed for hostname %s",
Lines 148-159 Link Here
148
			REJECT_PEER_NAME(state);
208
			REJECT_PEER_NAME(state);
149
			break;
209
			break;
150
		    }
210
		    }
151
		    if (memcmp(hp->h_addr_list[i],
211
		    if (memcmp(hp->h_addr_list[i], (char *)in,
152
			       (char *) &sin.sin_addr,
212
			       sizeof(*in)) == 0)
153
			       sizeof(sin.sin_addr)) == 0)
154
			break;			/* keep peer name */
213
			break;			/* keep peer name */
155
		}
214
		}
156
	    }
215
	    }
216
#endif
157
	}
217
	}
158
    }
218
    }
159
219
(-)postfix-1.1.11-20020613-orig/src/smtp/Makefile.in (+12 lines)
Lines 84-89 Link Here
84
smtp.o: ../../include/iostuff.h
84
smtp.o: ../../include/iostuff.h
85
smtp.o: ../../include/attr.h
85
smtp.o: ../../include/attr.h
86
smtp.o: ../../include/mail_server.h
86
smtp.o: ../../include/mail_server.h
87
smtp.o: ../../include/pfixtls.h
87
smtp.o: smtp.h
88
smtp.o: smtp.h
88
smtp.o: smtp_sasl.h
89
smtp.o: smtp_sasl.h
89
smtp_addr.o: smtp_addr.c
90
smtp_addr.o: smtp_addr.c
Lines 103-108 Link Here
103
smtp_addr.o: ../../include/argv.h
104
smtp_addr.o: ../../include/argv.h
104
smtp_addr.o: ../../include/deliver_request.h
105
smtp_addr.o: ../../include/deliver_request.h
105
smtp_addr.o: ../../include/recipient_list.h
106
smtp_addr.o: ../../include/recipient_list.h
107
smtp_addr.o: ../../include/pfixtls.h
106
smtp_addr.o: smtp_addr.h
108
smtp_addr.o: smtp_addr.h
107
smtp_chat.o: smtp_chat.c
109
smtp_chat.o: smtp_chat.c
108
smtp_chat.o: ../../include/sys_defs.h
110
smtp_chat.o: ../../include/sys_defs.h
Lines 123-128 Link Here
123
smtp_chat.o: ../../include/cleanup_user.h
125
smtp_chat.o: ../../include/cleanup_user.h
124
smtp_chat.o: ../../include/mail_error.h
126
smtp_chat.o: ../../include/mail_error.h
125
smtp_chat.o: ../../include/name_mask.h
127
smtp_chat.o: ../../include/name_mask.h
128
smtp_chat.o: ../../include/pfixtls.h
126
smtp_chat.o: smtp.h
129
smtp_chat.o: smtp.h
127
smtp_connect.o: smtp_connect.c
130
smtp_connect.o: smtp_connect.c
128
smtp_connect.o: ../../include/sys_defs.h
131
smtp_connect.o: ../../include/sys_defs.h
Lines 139-148 Link Here
139
smtp_connect.o: ../../include/mail_params.h
142
smtp_connect.o: ../../include/mail_params.h
140
smtp_connect.o: ../../include/own_inet_addr.h
143
smtp_connect.o: ../../include/own_inet_addr.h
141
smtp_connect.o: ../../include/dns.h
144
smtp_connect.o: ../../include/dns.h
145
smtp_connect.o: ../../include/get_port.h
142
smtp_connect.o: smtp.h
146
smtp_connect.o: smtp.h
143
smtp_connect.o: ../../include/argv.h
147
smtp_connect.o: ../../include/argv.h
144
smtp_connect.o: ../../include/deliver_request.h
148
smtp_connect.o: ../../include/deliver_request.h
145
smtp_connect.o: ../../include/recipient_list.h
149
smtp_connect.o: ../../include/recipient_list.h
150
smtp_connetc.o: ../../include/pfixtls.h
146
smtp_connect.o: smtp_addr.h
151
smtp_connect.o: smtp_addr.h
147
smtp_proto.o: smtp_proto.c
152
smtp_proto.o: smtp_proto.c
148
smtp_proto.o: ../../include/sys_defs.h
153
smtp_proto.o: ../../include/sys_defs.h
Lines 174-179 Link Here
174
smtp_proto.o: ../../include/attr.h
179
smtp_proto.o: ../../include/attr.h
175
smtp_proto.o: ../../include/mime_state.h
180
smtp_proto.o: ../../include/mime_state.h
176
smtp_proto.o: ../../include/header_opts.h
181
smtp_proto.o: ../../include/header_opts.h
182
smtp_proto.o: ../../include/pfixtls.h
177
smtp_proto.o: smtp.h
183
smtp_proto.o: smtp.h
178
smtp_proto.o: ../../include/argv.h
184
smtp_proto.o: ../../include/argv.h
179
smtp_proto.o: smtp_sasl.h
185
smtp_proto.o: smtp_sasl.h
Lines 219-227 Link Here
219
smtp_session.o: ../../include/stringops.h
225
smtp_session.o: ../../include/stringops.h
220
smtp_session.o: ../../include/vstring.h
226
smtp_session.o: ../../include/vstring.h
221
smtp_session.o: smtp.h
227
smtp_session.o: smtp.h
228
smtp_session.o: ../../include/mail_params.h
229
smtp_session.o: ../../include/pfixtls.h
222
smtp_session.o: ../../include/argv.h
230
smtp_session.o: ../../include/argv.h
223
smtp_session.o: ../../include/deliver_request.h
231
smtp_session.o: ../../include/deliver_request.h
224
smtp_session.o: ../../include/recipient_list.h
232
smtp_session.o: ../../include/recipient_list.h
233
smtp_session.o: ../../include/maps.h
225
smtp_state.o: smtp_state.c
234
smtp_state.o: smtp_state.c
226
smtp_state.o: ../../include/sys_defs.h
235
smtp_state.o: ../../include/sys_defs.h
227
smtp_state.o: ../../include/mymalloc.h
236
smtp_state.o: ../../include/mymalloc.h
Lines 235-240 Link Here
235
smtp_state.o: ../../include/argv.h
244
smtp_state.o: ../../include/argv.h
236
smtp_state.o: ../../include/deliver_request.h
245
smtp_state.o: ../../include/deliver_request.h
237
smtp_state.o: ../../include/recipient_list.h
246
smtp_state.o: ../../include/recipient_list.h
247
smtp_state.o: ../../include/pfixtls.h
238
smtp_state.o: smtp_sasl.h
248
smtp_state.o: smtp_sasl.h
239
smtp_trouble.o: smtp_trouble.c
249
smtp_trouble.o: smtp_trouble.c
240
smtp_trouble.o: ../../include/sys_defs.h
250
smtp_trouble.o: ../../include/sys_defs.h
Lines 254-259 Link Here
254
smtp_trouble.o: ../../include/name_mask.h
264
smtp_trouble.o: ../../include/name_mask.h
255
smtp_trouble.o: smtp.h
265
smtp_trouble.o: smtp.h
256
smtp_trouble.o: ../../include/argv.h
266
smtp_trouble.o: ../../include/argv.h
267
smtp_trouble.o: ../../include/pfixtls.h
257
smtp_unalias.o: smtp_unalias.c
268
smtp_unalias.o: smtp_unalias.c
258
smtp_unalias.o: ../../include/sys_defs.h
269
smtp_unalias.o: ../../include/sys_defs.h
259
smtp_unalias.o: ../../include/htable.h
270
smtp_unalias.o: ../../include/htable.h
Lines 266-268 Link Here
266
smtp_unalias.o: ../../include/argv.h
277
smtp_unalias.o: ../../include/argv.h
267
smtp_unalias.o: ../../include/deliver_request.h
278
smtp_unalias.o: ../../include/deliver_request.h
268
smtp_unalias.o: ../../include/recipient_list.h
279
smtp_unalias.o: ../../include/recipient_list.h
280
smtp_unalias.o: ../../include/pfixtls.h
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp.c (-1 / +35 lines)
Line 0 Link Here
1
--- smtp_proto.c.old	Wed May 15 14:01:56 2002
Lines 100-106 Link Here
100
/* .IP \fBsmtp_never_send_ehlo\fR
100
/* .IP \fBsmtp_never_send_ehlo\fR
101
/*	Never send EHLO at the start of a connection.
101
/*	Never send EHLO at the start of a connection.
102
/* .IP \fBsmtp_bind_address\fR
102
/* .IP \fBsmtp_bind_address\fR
103
/*	Numerical source network address to bind to when making a connection.
103
/*	Numerical source network address (IPv4) to bind to when making
104
/*	a connection.
105
/* .IP \fBsmtp_bind_address6\fR
106
/*	Numerical source network address (IPv6) to bind to when making
107
/*	a connection.
104
/* .IP \fBsmtp_line_length_limit\fR
108
/* .IP \fBsmtp_line_length_limit\fR
105
/*	Length limit for SMTP message content lines. Zero means no limit.
109
/*	Length limit for SMTP message content lines. Zero means no limit.
106
/*	Some SMTP servers misbehave on long lines.
110
/*	Some SMTP servers misbehave on long lines.
Lines 240-245 Link Here
240
#include <debug_peer.h>
244
#include <debug_peer.h>
241
#include <mail_error.h>
245
#include <mail_error.h>
242
#include <deliver_pass.h>
246
#include <deliver_pass.h>
247
#include <pfixtls.h>
243
248
244
/* Single server skeleton. */
249
/* Single server skeleton. */
245
250
Lines 256-261 Link Here
256
  */
261
  */
257
int     var_smtp_conn_tmout;
262
int     var_smtp_conn_tmout;
258
int     var_smtp_helo_tmout;
263
int     var_smtp_helo_tmout;
264
int     var_smtp_starttls_tmout;
259
int     var_smtp_mail_tmout;
265
int     var_smtp_mail_tmout;
260
int     var_smtp_rcpt_tmout;
266
int     var_smtp_rcpt_tmout;
261
int     var_smtp_data0_tmout;
267
int     var_smtp_data0_tmout;
Lines 277-287 Link Here
277
char   *var_smtp_sasl_passwd;
283
char   *var_smtp_sasl_passwd;
278
bool    var_smtp_sasl_enable;
284
bool    var_smtp_sasl_enable;
279
char   *var_smtp_bind_addr;
285
char   *var_smtp_bind_addr;
286
#ifdef INET6
287
char   *var_smtp_bind_addr6;
288
#endif
280
bool    var_smtp_rand_addr;
289
bool    var_smtp_rand_addr;
281
int     var_smtp_pix_thresh;
290
int     var_smtp_pix_thresh;
282
int     var_smtp_pix_delay;
291
int     var_smtp_pix_delay;
283
int     var_smtp_line_limit;
292
int     var_smtp_line_limit;
284
char   *var_smtp_helo_name;
293
char   *var_smtp_helo_name;
294
int     var_smtp_use_tls;
295
int     var_smtp_enforce_tls;
296
int     var_smtp_tls_enforce_peername;
297
char   *var_smtp_tls_per_site;
298
int     var_smtp_tls_scert_vd;
299
int     var_smtp_tls_note_starttls_offer;
285
300
286
 /*
301
 /*
287
  * Global variables. smtp_errno is set by the address lookup routines and by
302
  * Global variables. smtp_errno is set by the address lookup routines and by
Lines 391-396 Link Here
391
406
392
static void pre_init(char *unused_name, char **unused_argv)
407
static void pre_init(char *unused_name, char **unused_argv)
393
{
408
{
409
394
    debug_peer_init();
410
    debug_peer_init();
395
411
396
    if (var_smtp_sasl_enable)
412
    if (var_smtp_sasl_enable)
Lines 400-405 Link Here
400
	msg_warn("%s is true, but SASL support is not compiled in",
416
	msg_warn("%s is true, but SASL support is not compiled in",
401
		 VAR_SMTP_SASL_ENABLE);
417
		 VAR_SMTP_SASL_ENABLE);
402
#endif
418
#endif
419
    /*
420
     * Initialize the TLS data before entering the chroot jail
421
     */
422
#ifdef HAS_SSL
423
    if (var_smtp_use_tls || var_smtp_enforce_tls || var_smtp_tls_per_site[0])
424
	pfixtls_init_clientengine(var_smtp_tls_scert_vd);
425
    smtp_tls_list_init();
426
#endif
403
}
427
}
404
428
405
/* pre_accept - see if tables have changed */
429
/* pre_accept - see if tables have changed */
Lines 434-440 Link Here
434
	VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
458
	VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
435
	VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
459
	VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
436
	VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
460
	VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
461
#ifdef INET6
462
	VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
463
#endif
437
	VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
464
	VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
465
	VAR_SMTP_TLS_PER_SITE, DEF_SMTP_TLS_PER_SITE, &var_smtp_tls_per_site, 0, 0,
438
	0,
466
	0,
439
    };
467
    };
440
    static CONFIG_TIME_TABLE time_table[] = {
468
    static CONFIG_TIME_TABLE time_table[] = {
Lines 448-453 Link Here
448
	VAR_SMTP_QUIT_TMOUT, DEF_SMTP_QUIT_TMOUT, &var_smtp_quit_tmout, 1, 0,
476
	VAR_SMTP_QUIT_TMOUT, DEF_SMTP_QUIT_TMOUT, &var_smtp_quit_tmout, 1, 0,
449
	VAR_SMTP_PIX_THRESH, DEF_SMTP_PIX_THRESH, &var_smtp_pix_thresh, 0, 0,
477
	VAR_SMTP_PIX_THRESH, DEF_SMTP_PIX_THRESH, &var_smtp_pix_thresh, 0, 0,
450
	VAR_SMTP_PIX_DELAY, DEF_SMTP_PIX_DELAY, &var_smtp_pix_delay, 1, 0,
478
	VAR_SMTP_PIX_DELAY, DEF_SMTP_PIX_DELAY, &var_smtp_pix_delay, 1, 0,
479
	VAR_SMTP_STARTTLS_TMOUT, DEF_SMTP_STARTTLS_TMOUT, &var_smtp_starttls_tmout, 1, 0,
451
	0,
480
	0,
452
    };
481
    };
453
    static CONFIG_INT_TABLE int_table[] = {
482
    static CONFIG_INT_TABLE int_table[] = {
Lines 463-468 Link Here
463
	VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
492
	VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
464
	VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
493
	VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
465
	VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
494
	VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
495
	VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls,
496
	VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_tls,
497
	VAR_SMTP_TLS_ENFORCE_PN, DEF_SMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername,
498
	VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
466
	0,
499
	0,
467
    };
500
    };
468
501
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp.h (-1 / +7 lines)
Lines 27-32 Link Here
27
  * Global library.
27
  * Global library.
28
  */
28
  */
29
#include <deliver_request.h>
29
#include <deliver_request.h>
30
#include <pfixtls.h>
30
31
31
 /*
32
 /*
32
  * State information associated with each SMTP delivery. We're bundling the
33
  * State information associated with each SMTP delivery. We're bundling the
Lines 79-87 Link Here
79
    char   *addr;			/* mail exchanger */
80
    char   *addr;			/* mail exchanger */
80
    char   *namaddr;			/* mail exchanger */
81
    char   *namaddr;			/* mail exchanger */
81
    int     best;			/* most preferred host */
82
    int     best;			/* most preferred host */
83
    int     tls_use_tls;		/* can do TLS */
84
    int     tls_enforce_tls;		/* must do TLS */
85
    int     tls_enforce_peername;	/* cert must match */
86
    tls_info_t tls_info;		/* TLS connection state */
82
} SMTP_SESSION;
87
} SMTP_SESSION;
83
88
84
extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, char *, char *);
89
extern void smtp_tls_list_init(void);
90
extern SMTP_SESSION *smtp_session_alloc(char *, VSTREAM *, char *, char *);
85
extern void smtp_session_free(SMTP_SESSION *);
91
extern void smtp_session_free(SMTP_SESSION *);
86
92
87
 /*
93
 /*
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp_addr.c (-10 / +137 lines)
Lines 134-151 Link Here
134
static void smtp_print_addr(char *what, DNS_RR *addr_list)
134
static void smtp_print_addr(char *what, DNS_RR *addr_list)
135
{
135
{
136
    DNS_RR *addr;
136
    DNS_RR *addr;
137
    struct in_addr in_addr;
137
#ifdef INET6
138
    struct sockaddr_storage ss;
139
#else
140
    struct sockaddr ss;
141
#endif
142
    struct sockaddr_in *sin;
143
#ifdef INET6
144
    struct sockaddr_in6 *sin6;
145
    char   hbuf[NI_MAXHOST];
146
#else
147
    char   hbuf[sizeof("255.255.255.255") + 1];
148
#endif
138
149
139
    msg_info("begin %s address list", what);
150
    msg_info("begin %s address list", what);
140
    for (addr = addr_list; addr; addr = addr->next) {
151
    for (addr = addr_list; addr; addr = addr->next) {
141
	if (addr->data_len > sizeof(addr)) {
152
	if (addr->class != C_IN) {
142
	    msg_warn("skipping address length %d", addr->data_len);
153
	    msg_warn("skipping unsupported address (class=%u)", addr->class);
143
	} else {
154
	    continue;
144
	    memcpy((char *) &in_addr, addr->data, sizeof(in_addr));
145
	    msg_info("pref %4d host %s/%s",
146
		     addr->pref, addr->name,
147
		     inet_ntoa(in_addr));
148
	}
155
	}
156
	switch (addr->type) {
157
	case T_A:
158
	    if (addr->data_len != sizeof(sin->sin_addr)) {
159
		msg_warn("skipping invalid address (AAAA, len=%u)",
160
		    addr->data_len);
161
		continue;
162
	    }
163
	    sin = (struct sockaddr_in *)&ss;
164
	    memset(sin, 0, sizeof(*sin));
165
	    sin->sin_family = AF_INET;
166
#ifdef HAS_SA_LEN
167
	    sin->sin_len = sizeof(*sin);
168
#endif
169
	    memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
170
	    break;
171
#ifdef INET6
172
	case T_AAAA:
173
	    if (addr->data_len != sizeof(sin6->sin6_addr)) {
174
		msg_warn("skipping invalid address (AAAA, len=%u)",
175
		    addr->data_len);
176
		continue;
177
	    }
178
	    sin6 = (struct sockaddr_in6 *)&ss;
179
	    memset(sin6, 0, sizeof(*sin6));
180
	    sin6->sin6_family = AF_INET6;
181
#ifdef HAS_SA_LEN
182
	    sin6->sin6_len = sizeof(*sin6);
183
#endif
184
	    memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
185
	    break;
186
#endif
187
	default:
188
	    msg_warn("skipping unsupported address (type=%u)", addr->type);
189
	    continue;
190
	}
191
192
#ifdef INET6
193
	(void)getnameinfo((struct sockaddr *)&ss, SS_LEN(ss),
194
	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
195
#else
196
	(void)inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
197
#endif
198
	msg_info("pref %4d host %s/%s", addr->pref, addr->name, hbuf);
149
    }
199
    }
150
    msg_info("end %s address list", what);
200
    msg_info("end %s address list", what);
151
}
201
}
Lines 155-169 Link Here
155
static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
205
static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
156
{
206
{
157
    char   *myname = "smtp_addr_one";
207
    char   *myname = "smtp_addr_one";
208
#ifndef INET6
158
    struct in_addr inaddr;
209
    struct in_addr inaddr;
159
    DNS_FIXED fixed;
160
    DNS_RR *addr = 0;
210
    DNS_RR *addr = 0;
161
    DNS_RR *rr;
211
    DNS_RR *rr;
162
    struct hostent *hp;
212
    struct hostent *hp;
213
#else
214
    struct addrinfo hints, *res0, *res;
215
    int error = -1;
216
    char *addr;
217
    size_t addrlen;
218
#endif
219
    DNS_FIXED fixed;
163
220
164
    if (msg_verbose)
221
    if (msg_verbose)
165
	msg_info("%s: host %s", myname, host);
222
	msg_info("%s: host %s", myname, host);
166
223
224
#ifndef INET6
167
    /*
225
    /*
168
     * Interpret a numerical name as an address.
226
     * Interpret a numerical name as an address.
169
     */
227
     */
Lines 216-221 Link Here
216
	smtp_errno = SMTP_FAIL;
274
	smtp_errno = SMTP_FAIL;
217
	break;
275
	break;
218
    }
276
    }
277
#else
278
    memset(&hints, 0, sizeof(hints));
279
    hints.ai_family = PF_UNSPEC;
280
    hints.ai_socktype = SOCK_STREAM;
281
    error = getaddrinfo(host, NULL, &hints, &res0);
282
    if (error) {
283
	switch (error) {
284
	case EAI_AGAIN:
285
	    smtp_errno = SMTP_RETRY;
286
	    break;
287
	default:
288
	    vstring_sprintf(why, "[%s]: %s",host,gai_strerror(error));
289
	    smtp_errno = SMTP_FAIL;
290
	    break;
291
	}
292
	return (addr_list);
293
    }
294
    for (res = res0; res; res = res->ai_next) {
295
	memset((char *) &fixed, 0, sizeof(fixed));
296
	switch(res->ai_family) {
297
	case AF_INET6:
298
	    /* XXX not scope friendly */
299
	    fixed.type = T_AAAA;
300
	    addr = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
301
	    addrlen = sizeof(struct in6_addr);
302
	    break;
303
	case AF_INET:
304
	    fixed.type = T_A;
305
	    addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
306
	    addrlen = sizeof(struct in_addr);
307
	    break;
308
	default:
309
	    msg_warn("%s: unknown address family %d for %s",
310
	        myname, res->ai_family, host);
311
	    continue;
312
	}
313
	addr_list = dns_rr_append(addr_list,
314
	    dns_rr_create(host, &fixed, pref, addr, addrlen));
315
    }
316
    if (res0)
317
	freeaddrinfo(res0);
318
#endif
219
    return (addr_list);
319
    return (addr_list);
220
}
320
}
221
321
Lines 251-256 Link Here
251
    INET_ADDR_LIST *self;
351
    INET_ADDR_LIST *self;
252
    DNS_RR *addr;
352
    DNS_RR *addr;
253
    int     i;
353
    int     i;
354
#ifdef INET6
355
    struct sockaddr *sa;
356
#endif
254
357
255
    /*
358
    /*
256
     * Find the first address that lists any address that this mail system is
359
     * Find the first address that lists any address that this mail system is
Lines 260-271 Link Here
260
363
261
    self = own_inet_addr_list();
364
    self = own_inet_addr_list();
262
    for (addr = addr_list; addr; addr = addr->next) {
365
    for (addr = addr_list; addr; addr = addr->next) {
263
	for (i = 0; i < self->used; i++)
366
	for (i = 0; i < self->used; i++) {
367
#ifdef INET6
368
	    sa = (struct sockaddr *)&self->addrs[i];
369
	    switch(addr->type) {
370
	    case T_AAAA:
371
		/* XXX scope */
372
		if (sa->sa_family != AF_INET6)
373
		    break;
374
		if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
375
			addr->data, sizeof(struct in6_addr)) == 0) {
376
		    return(addr);
377
		}
378
		break;
379
	    case T_A:
380
		if (sa->sa_family != AF_INET)
381
		    break;
382
		if (memcmp(&((struct sockaddr_in *)sa)->sin_addr,
383
			addr->data, sizeof(struct in_addr)) == 0) {
384
		    return(addr);
385
		}
386
		break;
387
	    }
388
#else
264
	    if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
389
	    if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
265
		if (msg_verbose)
390
		if (msg_verbose)
266
		    msg_info("%s: found at pref %d", myname, addr->pref);
391
		    msg_info("%s: found at pref %d", myname, addr->pref);
267
		return (addr);
392
		return (addr);
268
	    }
393
	    }
394
#endif
395
	}
269
    }
396
    }
270
397
271
    /*
398
    /*
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp_connect.c (-31 / +169 lines)
Lines 81-86 Link Here
81
/* System library. */
81
/* System library. */
82
82
83
#include <sys_defs.h>
83
#include <sys_defs.h>
84
#include <stdlib.h>
84
#include <sys/socket.h>
85
#include <sys/socket.h>
85
#include <netinet/in.h>
86
#include <netinet/in.h>
86
#include <arpa/inet.h>
87
#include <arpa/inet.h>
Lines 110-121 Link Here
110
#include <inet_addr_list.h>
111
#include <inet_addr_list.h>
111
#include <iostuff.h>
112
#include <iostuff.h>
112
#include <timed_connect.h>
113
#include <timed_connect.h>
114
#include <get_port.h>
113
#include <stringops.h>
115
#include <stringops.h>
114
116
115
/* Global library. */
117
/* Global library. */
116
118
117
#include <mail_params.h>
119
#include <mail_params.h>
118
#include <own_inet_addr.h>
120
#include <own_inet_addr.h>
121
#include <pfixtls.h>
119
122
120
/* DNS library. */
123
/* DNS library. */
121
124
Lines 128-150 Link Here
128
131
129
/* smtp_connect_addr - connect to explicit address */
132
/* smtp_connect_addr - connect to explicit address */
130
133
131
static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
134
static SMTP_SESSION *smtp_connect_addr(char *dest, DNS_RR *addr, unsigned port,
132
				               VSTRING *why)
135
				               VSTRING *why)
133
{
136
{
134
    char   *myname = "smtp_connect_addr";
137
    char   *myname = "smtp_connect_addr";
135
    struct sockaddr_in sin;
138
#ifdef INET6
136
    int     sock;
139
    struct sockaddr_storage ss;
140
#else
141
    struct sockaddr ss;
142
#endif
143
    struct sockaddr *sa;
144
    struct sockaddr_in *sin;
145
#ifdef INET6
146
    struct sockaddr_in6 *sin6;
147
#endif
148
    SOCKADDR_SIZE salen;
149
#ifdef INET6
150
    char hbuf[NI_MAXHOST];
151
#else
152
    char hbuf[sizeof("255.255.255.255") + 1];
153
#endif
154
    int     sock = -1;
137
    INET_ADDR_LIST *addr_list;
155
    INET_ADDR_LIST *addr_list;
138
    int     conn_stat;
156
    int     conn_stat;
139
    int     saved_errno;
157
    int     saved_errno;
140
    VSTREAM *stream;
158
    VSTREAM *stream;
141
    int     ch;
159
    int     ch;
142
    unsigned long inaddr;
160
    char    *bind_addr;
161
162
    sa = (struct sockaddr *)&ss;
163
    sin = (struct sockaddr_in *)&ss;
164
#ifdef INET6
165
    sin6 = (struct sockaddr_in6 *)&ss;
166
#endif
143
167
144
    /*
168
    /*
145
     * Sanity checks.
169
     * Sanity checks.
146
     */
170
     */
147
    if (addr->data_len > sizeof(sin.sin_addr)) {
171
#ifdef INET6
172
    if (((addr->type==T_A) && (addr->data_len > sizeof(sin->sin_addr))) ||
173
	((addr->type==T_AAAA) && (addr->data_len > sizeof(sin6->sin6_addr))))
174
#else
175
    if (addr->data_len > sizeof(sin->sin_addr))
176
#endif
177
    {
148
	msg_warn("%s: skip address with length %d", myname, addr->data_len);
178
	msg_warn("%s: skip address with length %d", myname, addr->data_len);
149
	smtp_errno = SMTP_RETRY;
179
	smtp_errno = SMTP_RETRY;
150
	return (0);
180
	return (0);
Lines 153-170 Link Here
153
    /*
183
    /*
154
     * Initialize.
184
     * Initialize.
155
     */
185
     */
156
    memset((char *) &sin, 0, sizeof(sin));
186
    switch (addr->type) {
157
    sin.sin_family = AF_INET;
187
#ifdef INET6
158
188
    case T_AAAA:
159
    if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
189
	bind_addr = var_smtp_bind_addr6;
160
	msg_fatal("%s: socket: %m", myname);
190
	memset(sin6, 0, sizeof(*sin6));
161
191
	sin6->sin6_family = AF_INET6;
192
	salen = sizeof(*sin6);
193
	break;
194
#endif
195
    default: /* T_A: */
196
	bind_addr = var_smtp_bind_addr;
197
	memset(sin, 0, sizeof(*sin));
198
	sin->sin_family = AF_INET;
199
	salen = sizeof(*sin);
200
	break;
201
    }
202
#ifdef HAS_SA_LEN
203
    sa->sa_len = salen;
204
#endif
205
    if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
206
	msg_warn("%s: socket: %m", myname);
207
		    
162
    /*
208
    /*
163
     * Allow the sysadmin to specify the source address, for example, as "-o
209
     * Allow the sysadmin to specify the source address, for example, as "-o
164
     * smtp_bind_address=x.x.x.x" in the master.cf file.
210
     * smtp_bind_address=x.x.x.x" in the master.cf file.
165
     */
211
     */
166
    if (*var_smtp_bind_addr) {
212
    if (*bind_addr) {
167
	sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr);
213
#ifndef INET6
214
	struct sockaddr_in sin;
215
216
	memset(&sin, 0, sizeof(sin));
217
	sin.sin_family = AF_INET;
218
#ifdef HAS_SA_LEN
219
	sin.sin_len = sizeof(sin);
220
#endif
221
	sin.sin_addr.s_addr = inet_addr(bind_addr);
168
	if (sin.sin_addr.s_addr == INADDR_NONE)
222
	if (sin.sin_addr.s_addr == INADDR_NONE)
169
	    msg_fatal("%s: bad %s parameter: %s",
223
	    msg_fatal("%s: bad %s parameter: %s",
170
		      myname, VAR_SMTP_BIND_ADDR, var_smtp_bind_addr);
224
		      myname, VAR_SMTP_BIND_ADDR, var_smtp_bind_addr);
Lines 172-177 Link Here
172
	    msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
226
	    msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
173
	if (msg_verbose)
227
	if (msg_verbose)
174
	    msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
228
	    msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
229
#else
230
	char hbufl[NI_MAXHOST];
231
	struct addrinfo hints, *res;
232
233
	memset(&hints, 0, sizeof(hints));
234
	hints.ai_family = sa->sa_family;
235
	hints.ai_socktype = SOCK_STREAM;
236
	hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
237
	snprintf(hbufl, sizeof(hbufl)-1, "%s", bind_addr);
238
	if (getaddrinfo(hbufl, NULL, &hints, &res) == 0) {
239
	    (void)getnameinfo(res->ai_addr, res->ai_addrlen, hbufl,
240
	        sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
241
	    if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
242
		msg_warn("%s: bind %s: %m", myname, hbufl);
243
	    freeaddrinfo(res);
244
	    if (msg_verbose)
245
		msg_info("%s: bind %s", myname, hbufl);
246
	}
247
#endif
175
    }
248
    }
176
249
177
    /*
250
    /*
Lines 179-186 Link Here
179
     * the mail appears to come from the "right" machine address.
252
     * the mail appears to come from the "right" machine address.
180
     */
253
     */
181
    else if ((addr_list = own_inet_addr_list())->used == 1) {
254
    else if ((addr_list = own_inet_addr_list())->used == 1) {
255
#ifndef INET6
256
	struct sockaddr_in sin;
257
	unsigned long inaddr;	/*XXX BAD!*/
258
259
	memset(&sin, 0, sizeof(sin));
260
	sin.sin_family = AF_INET;
261
#ifdef HAS_SA_LEN
262
	sin.sin_len = sizeof(sin);
263
#endif
182
	memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
264
	memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
183
	inaddr = ntohl(sin.sin_addr.s_addr);
265
	inaddr = (unsigned long)ntohl(sin.sin_addr.s_addr);
184
	if (!IN_CLASSA(inaddr)
266
	if (!IN_CLASSA(inaddr)
185
	    || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
267
	    || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
186
	    if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
268
	    if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
Lines 188-217 Link Here
188
	    if (msg_verbose)
270
	    if (msg_verbose)
189
		msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
271
		msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
190
	}
272
	}
273
#else
274
	char hbufl[NI_MAXHOST];
275
	struct addrinfo hints, *res = NULL, *loopback = NULL;
276
277
	memset(&hints, 0, sizeof(hints));
278
	hints.ai_family = sa->sa_family;
279
	hints.ai_socktype = SOCK_STREAM;
280
	if (getaddrinfo(NULL, "0", &hints, &loopback) != 0)
281
	    loopback = NULL;
282
283
	/*
284
	 * getnameinfo -> getaddrinfo loop is here so that we can
285
	 * get rid of port.
286
	 */
287
	(void)getnameinfo((struct sockaddr *)addr_list->addrs, SA_LEN((struct sockaddr *)addr_list->addrs),
288
	    hbufl, sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
289
	hbufl[sizeof(hbufl)-1] = 0;
290
	memset(&hints, 0, sizeof(hints));
291
	hints.ai_family = sa->sa_family;
292
	hints.ai_socktype = SOCK_STREAM;
293
	hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
294
	if (getaddrinfo(hbufl, NULL, &hints, &res) == 0 &&
295
	    !(res->ai_addrlen == loopback->ai_addrlen &&
296
	      memcmp(res->ai_addr, loopback->ai_addr, res->ai_addrlen) == 0)) {
297
	    if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
298
		msg_warn("%s: bind %s: %m", myname, hbufl);
299
	    if (msg_verbose)
300
		msg_info("%s: bind %s", myname, hbufl);
301
	}
302
	if (res)
303
	    freeaddrinfo(res);
304
	if (loopback)
305
	    freeaddrinfo(loopback);
306
#endif
191
    }
307
    }
192
308
193
    /*
309
    /*
194
     * Connect to the SMTP server.
310
     * Connect to the SMTP server.
195
     */
311
     */
196
    sin.sin_port = port;
312
    switch (addr->type) {
197
    memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
313
#ifdef INET6
314
    case T_AAAA:
315
	/* XXX scope unfriendly */
316
	memset(sin6, 0, sizeof(*sin6));
317
	sin6->sin6_port = port;
318
	sin6->sin6_family = AF_INET6;
319
	salen = sizeof(*sin6);
320
	memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
321
	inet_ntop(AF_INET6, &sin6->sin6_addr, hbuf, sizeof(hbuf));
322
	break;
323
#endif
324
    default: /* T_A */
325
	memset(sin, 0, sizeof(*sin));
326
	sin->sin_port = port;
327
	sin->sin_family = AF_INET;
328
	salen = sizeof(*sin);
329
	memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
330
	inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
331
	break;
332
    }
333
#ifdef HAS_SA_LEN
334
    sa->sa_len = salen;
335
#endif
198
336
199
    if (msg_verbose)
337
    if (msg_verbose)
200
	msg_info("%s: trying: %s[%s] port %d...",
338
	msg_info("%s: trying: %s[%s] port %d...",
201
		 myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
339
		 myname, addr->name, hbuf, ntohs(port));
202
    if (var_smtp_conn_tmout > 0) {
340
    if (var_smtp_conn_tmout > 0) {
203
	non_blocking(sock, NON_BLOCKING);
341
	non_blocking(sock, NON_BLOCKING);
204
	conn_stat = timed_connect(sock, (struct sockaddr *) & sin,
342
	conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout);
205
				  sizeof(sin), var_smtp_conn_tmout);
206
	saved_errno = errno;
343
	saved_errno = errno;
207
	non_blocking(sock, BLOCKING);
344
	non_blocking(sock, BLOCKING);
208
	errno = saved_errno;
345
	errno = saved_errno;
209
    } else {
346
    } else {
210
	conn_stat = connect(sock, (struct sockaddr *) & sin, sizeof(sin));
347
	conn_stat = connect(sock, sa, salen);
211
    }
348
    }
212
    if (conn_stat < 0) {
349
    if (conn_stat < 0) {
213
	vstring_sprintf(why, "connect to %s[%s]: %m",
350
	vstring_sprintf(why, "connect to %s[%s]: %m",
214
			addr->name, inet_ntoa(sin.sin_addr));
351
			addr->name, hbuf);
215
	smtp_errno = SMTP_RETRY;
352
	smtp_errno = SMTP_RETRY;
216
	close(sock);
353
	close(sock);
217
	return (0);
354
	return (0);
Lines 221-228 Link Here
221
     * Skip this host if it takes no action within some time limit.
358
     * Skip this host if it takes no action within some time limit.
222
     */
359
     */
223
    if (read_wait(sock, var_smtp_helo_tmout) < 0) {
360
    if (read_wait(sock, var_smtp_helo_tmout) < 0) {
224
	vstring_sprintf(why, "connect to %s[%s]: read timeout",
361
	vstring_sprintf(why, "connect to %s [%s]: read timeout",
225
			addr->name, inet_ntoa(sin.sin_addr));
362
			addr->name, hbuf);
226
	smtp_errno = SMTP_RETRY;
363
	smtp_errno = SMTP_RETRY;
227
	close(sock);
364
	close(sock);
228
	return (0);
365
	return (0);
Lines 233-240 Link Here
233
     */
370
     */
234
    stream = vstream_fdopen(sock, O_RDWR);
371
    stream = vstream_fdopen(sock, O_RDWR);
235
    if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
372
    if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
236
	vstring_sprintf(why, "connect to %s[%s]: server dropped connection",
373
	vstring_sprintf(why, "connect to %s [%s]: server dropped connection",
237
			addr->name, inet_ntoa(sin.sin_addr));
374
			addr->name, hbuf);
238
	smtp_errno = SMTP_RETRY;
375
	smtp_errno = SMTP_RETRY;
239
	vstream_fclose(stream);
376
	vstream_fclose(stream);
240
	return (0);
377
	return (0);
Lines 246-252 Link Here
246
     */
383
     */
247
    if (ch == '4' && var_smtp_skip_4xx_greeting) {
384
    if (ch == '4' && var_smtp_skip_4xx_greeting) {
248
	vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
385
	vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
249
			addr->name, inet_ntoa(sin.sin_addr));
386
			addr->name, hbuf);
250
	smtp_errno = SMTP_RETRY;
387
	smtp_errno = SMTP_RETRY;
251
	vstream_fclose(stream);
388
	vstream_fclose(stream);
252
	return (0);
389
	return (0);
Lines 257-268 Link Here
257
     */
394
     */
258
    if (ch == '5' && var_smtp_skip_5xx_greeting) {
395
    if (ch == '5' && var_smtp_skip_5xx_greeting) {
259
	vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
396
	vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
260
			addr->name, inet_ntoa(sin.sin_addr));
397
			addr->name, hbuf);
261
	smtp_errno = SMTP_RETRY;
398
	smtp_errno = SMTP_RETRY;
262
	vstream_fclose(stream);
399
	vstream_fclose(stream);
263
	return (0);
400
	return (0);
264
    }
401
    }
265
    return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
402
    return (smtp_session_alloc(dest, stream, addr->name, hbuf));
266
}
403
}
267
404
268
/* smtp_connect_host - direct connection to host */
405
/* smtp_connect_host - direct connection to host */
Lines 272-278 Link Here
272
    SMTP_SESSION *session = 0;
409
    SMTP_SESSION *session = 0;
273
    DNS_RR *addr_list;
410
    DNS_RR *addr_list;
274
    DNS_RR *addr;
411
    DNS_RR *addr;
275
412
    
276
    /*
413
    /*
277
     * Try each address in the specified order until we find one that works.
414
     * Try each address in the specified order until we find one that works.
278
     * The addresses belong to the same A record, so we have no information
415
     * The addresses belong to the same A record, so we have no information
Lines 280-286 Link Here
280
     */
417
     */
281
    addr_list = smtp_host_addr(host, why);
418
    addr_list = smtp_host_addr(host, why);
282
    for (addr = addr_list; addr; addr = addr->next) {
419
    for (addr = addr_list; addr; addr = addr->next) {
283
	if ((session = smtp_connect_addr(addr, port, why)) != 0) {
420
	if ((session = smtp_connect_addr(host, addr, port, why)) != 0) {
284
	    session->best = 1;
421
	    session->best = 1;
285
	    break;
422
	    break;
286
	}
423
	}
Lines 309-315 Link Here
309
     */
446
     */
310
    addr_list = smtp_domain_addr(name, why, found_myself);
447
    addr_list = smtp_domain_addr(name, why, found_myself);
311
    for (addr = addr_list; addr; addr = addr->next) {
448
    for (addr = addr_list; addr; addr = addr->next) {
312
	if ((session = smtp_connect_addr(addr, port, why)) != 0) {
449
	if ((session = smtp_connect_addr(name, addr, port, why)) != 0) {
313
	    session->best = (addr->pref == addr_list->pref);
450
	    session->best = (addr->pref == addr_list->pref);
314
	    break;
451
	    break;
315
	}
452
	}
Lines 379-384 Link Here
379
	    msg_fatal("unknown service: %s/%s", service, protocol);
516
	    msg_fatal("unknown service: %s/%s", service, protocol);
380
	*portp = sp->s_port;
517
	*portp = sp->s_port;
381
    }
518
    }
519
382
    return (buf);
520
    return (buf);
383
}
521
}
384
522
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp_proto.c (-1 / +130 lines)
Lines 103-108 Link Here
103
#include <quote_821_local.h>
103
#include <quote_821_local.h>
104
#include <mail_proto.h>
104
#include <mail_proto.h>
105
#include <mime_state.h>
105
#include <mime_state.h>
106
#include <pfixtls.h>
106
107
107
/* Application-specific. */
108
/* Application-specific. */
108
109
Lines 170-175 Link Here
170
    char   *words;
171
    char   *words;
171
    char   *word;
172
    char   *word;
172
    int     n;
173
    int     n;
174
    int     oldfeatures;
175
    int     rval;
173
176
174
    /*
177
    /*
175
     * Prepare for disaster.
178
     * Prepare for disaster.
Lines 231-237 Link Here
231
				   session->namaddr,
234
				   session->namaddr,
232
				   translit(resp->str, "\n", " ")));
235
				   translit(resp->str, "\n", " ")));
233
    }
236
    }
234
237
    if (var_smtp_always_ehlo)
238
	state->features |= SMTP_FEATURE_ESMTP;
235
    /*
239
    /*
236
     * Pick up some useful features offered by the SMTP server. XXX Until we
240
     * Pick up some useful features offered by the SMTP server. XXX Until we
237
     * have a portable routine to convert from string to off_t with proper
241
     * have a portable routine to convert from string to off_t with proper
Lines 243-248 Link Here
243
     * MicroSoft implemented AUTH based on an old draft.
247
     * MicroSoft implemented AUTH based on an old draft.
244
     */
248
     */
245
    lines = resp->str;
249
    lines = resp->str;
250
    oldfeatures = state->features;		/* remember */
246
    while ((words = mystrtok(&lines, "\n")) != 0) {
251
    while ((words = mystrtok(&lines, "\n")) != 0) {
247
	if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t=")) != 0) {
252
	if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t=")) != 0) {
248
	    if (strcasecmp(word, "8BITMIME") == 0)
253
	    if (strcasecmp(word, "8BITMIME") == 0)
Lines 259-264 Link Here
259
			state->size_limit = off_cvt_string(word);
264
			state->size_limit = off_cvt_string(word);
260
		}
265
		}
261
	    }
266
	    }
267
	    else if (strcasecmp(word, "STARTTLS") == 0)
268
		state->features |= SMTP_FEATURE_STARTTLS;
262
#ifdef USE_SASL_AUTH
269
#ifdef USE_SASL_AUTH
263
	    else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
270
	    else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
264
		smtp_sasl_helo_auth(state, words);
271
		smtp_sasl_helo_auth(state, words);
Lines 276-281 Link Here
276
	msg_info("server features: 0x%x size %.0f",
283
	msg_info("server features: 0x%x size %.0f",
277
		 state->features, (double) state->size_limit);
284
		 state->features, (double) state->size_limit);
278
285
286
#ifdef HAS_SSL
287
    if ((state->features & SMTP_FEATURE_STARTTLS) &&
288
	(var_smtp_tls_note_starttls_offer) &&
289
	(!(session->tls_enforce_tls || session->tls_use_tls)))
290
 	msg_info("Host offered STARTTLS: [%s]", session->host);
291
    if ((session->tls_enforce_tls) &&
292
	!(state->features & SMTP_FEATURE_STARTTLS))
293
    {
294
	/*
295
	 * We are enforced to use TLS but it is not offered, so we will give
296
	 * up on this host. We won't even try STARTTLS, because we could
297
	 * receive a "500 command unrecognized" which would bounce the
298
	 * message. We instead want to delay until STARTTLS becomes
299
	 * available.
300
	 */
301
	return (smtp_site_fail(state, 450, "Could not start TLS: not offered"));
302
    }
303
    if ((session->tls_enforce_tls) && !pfixtls_clientengine) {
304
	/*
305
	 * We would like to start client TLS, but our own TLS-engine is
306
	 * not running.
307
	 */
308
	return (smtp_site_fail(state, 450,
309
		 "Could not start TLS: our TLS-engine not running"));
310
    }
311
    if ((state->features & SMTP_FEATURE_STARTTLS) &&
312
	((session->tls_use_tls && pfixtls_clientengine) ||
313
	 (session->tls_enforce_tls))) {
314
	/*
315
         * Try to use the TLS feature
316
         */
317
	smtp_chat_cmd(state, "STARTTLS");
318
	if ((resp = smtp_chat_resp(state))->code / 100 != 2) {
319
	    state->features &= ~SMTP_FEATURE_STARTTLS;
320
	    /*
321
	     * At this point a political decision is necessary. If we
322
	     * enforce usage of tls, we have to close the connection
323
	     * now.
324
	     */
325
	    if (session->tls_enforce_tls)
326
		return (smtp_site_fail(state, resp->code,
327
					 "host %s refused to start TLS: %s",
328
					   session->host,
329
					   translit(resp->str, "\n", " ")));
330
	} else {
331
	    if (rval = pfixtls_start_clienttls(session->stream,
332
					       var_smtp_starttls_tmout,
333
					       session->tls_enforce_peername,
334
					       session->host,
335
					       &(session->tls_info)))
336
		return (smtp_site_fail(state, 450,
337
				 "Could not start TLS: client failure"));
338
339
340
	    /*
341
	     * Now the connection is established and maybe we do have a
342
	     * validated cert with a CommonName in it.
343
	     * In enforce_peername state, the handshake would already have
344
	     * been terminated so the check here is for logging only!
345
	     */
346
	    if (session->tls_info.peer_CN != NULL) {
347
		if (!session->tls_info.peer_verified) {
348
		    msg_info("Peer certficate could not be verified");
349
		    if (session->tls_enforce_tls) {
350
			pfixtls_stop_clienttls(session->stream,
351
					       var_smtp_starttls_tmout, 1,
352
					       &(session->tls_info));
353
			return(smtp_site_fail(state, 450, "TLS-failure: Could not verify certificate"));
354
		    }
355
		}
356
	    } else if (session->tls_enforce_tls) {
357
		pfixtls_stop_clienttls(session->stream,
358
				       var_smtp_starttls_tmout, 1,
359
				       &(session->tls_info));
360
		return (smtp_site_fail(state, 450, "TLS-failure: Cannot verify hostname"));
361
	    }
362
363
	    /*
364
	     * At this point we have to re-negotiate the "EHLO" to reget
365
	     * the feature-list
366
	     */
367
	    state->features = oldfeatures;
368
#ifdef USE_SASL_AUTH
369
	    if (state->sasl_mechanism_list) {
370
		myfree(state->sasl_mechanism_list);
371
		state->sasl_mechanism_list = 0;
372
	    }
373
#endif
374
	    if (state->features & SMTP_FEATURE_ESMTP) {
375
		smtp_chat_cmd(state, "EHLO %s", var_myhostname);
376
		if ((resp = smtp_chat_resp(state))->code / 100 != 2)
377
		    state->features &= ~SMTP_FEATURE_ESMTP;
378
	    }
379
	    lines = resp->str;
380
	    (void) mystrtok(&lines, "\n");
381
	    while ((words = mystrtok(&lines, "\n")) != 0) {
382
		if (mystrtok(&words, "- ") &&
383
		    (word = mystrtok(&words, " \t=")) != 0) {
384
		    if (strcasecmp(word, "8BITMIME") == 0)
385
			state->features |= SMTP_FEATURE_8BITMIME;
386
		    else if (strcasecmp(word, "PIPELINING") == 0)
387
			state->features |= SMTP_FEATURE_PIPELINING;
388
		    else if (strcasecmp(word, "SIZE") == 0)
389
			state->features |= SMTP_FEATURE_SIZE;
390
		    else if (strcasecmp(word, "STARTTLS") == 0)
391
			state->features |= SMTP_FEATURE_STARTTLS;
392
#ifdef USE_SASL_AUTH
393
		    else if (var_smtp_sasl_enable &&
394
			     strcasecmp(word, "AUTH") == 0)
395
			smtp_sasl_helo_auth(state, words);
396
#endif
397
		}
398
	    }
399
	    /*
400
	     * Actually, at this point STARTTLS should not be offered
401
	     * anymore, so we could check for a protocol violation, but
402
	     * what should we do then?
403
	     */
404
405
	}
406
    }
407
#endif
279
#ifdef USE_SASL_AUTH
408
#ifdef USE_SASL_AUTH
280
    if (var_smtp_sasl_enable && (state->features & SMTP_FEATURE_AUTH))
409
    if (var_smtp_sasl_enable && (state->features & SMTP_FEATURE_AUTH))
281
	return (smtp_sasl_helo_login(state));
410
	return (smtp_sasl_helo_login(state));
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp_session.c (-1 / +88 lines)
Lines 42-56 Link Here
42
#include <vstream.h>
42
#include <vstream.h>
43
#include <stringops.h>
43
#include <stringops.h>
44
44
45
#include <mail_params.h>
46
#include <maps.h>
47
#include <pfixtls.h>
48
45
/* Application-specific. */
49
/* Application-specific. */
46
50
47
#include "smtp.h"
51
#include "smtp.h"
48
52
53
#ifdef HAS_SSL
54
/* static lists */
55
static MAPS *tls_per_site;
56
57
/* smtp_tls_list_init - initialize lists */
58
59
void smtp_tls_list_init(void)
60
{
61
    tls_per_site = maps_create(VAR_SMTP_TLS_PER_SITE, var_smtp_tls_per_site,
62
			       DICT_FLAG_LOCK);
63
}
64
#endif
65
49
/* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
66
/* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
50
67
51
SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, char *host, char *addr)
68
SMTP_SESSION *smtp_session_alloc(char *dest, VSTREAM *stream, char *host, char *addr)
52
{
69
{
53
    SMTP_SESSION *session;
70
    SMTP_SESSION *session;
71
    const char *lookup;
72
    char *lookup_key;
73
    int host_dont_use = 0;
74
    int host_use = 0;
75
    int host_enforce = 0;
76
    int host_enforce_peername = 0;
77
    int recipient_dont_use = 0;
78
    int recipient_use = 0;
79
    int recipient_enforce = 0;
80
    int recipient_enforce_peername = 0;
54
81
55
    session = (SMTP_SESSION *) mymalloc(sizeof(*session));
82
    session = (SMTP_SESSION *) mymalloc(sizeof(*session));
56
    session->stream = stream;
83
    session->stream = stream;
Lines 58-63 Link Here
58
    session->addr = mystrdup(addr);
85
    session->addr = mystrdup(addr);
59
    session->namaddr = concatenate(host, "[", addr, "]", (char *) 0);
86
    session->namaddr = concatenate(host, "[", addr, "]", (char *) 0);
60
    session->best = 1;
87
    session->best = 1;
88
    session->tls_use_tls = session->tls_enforce_tls = 0;
89
    session->tls_enforce_peername = 0;
90
#ifdef HAS_SSL
91
    lookup_key = lowercase(mystrdup(host));
92
    if (lookup = maps_find(tls_per_site, lookup_key, 0)) {
93
	if (!strcasecmp(lookup, "NONE"))
94
	    host_dont_use = 1;
95
	else if (!strcasecmp(lookup, "MAY"))
96
	    host_use = 1;
97
	else if (!strcasecmp(lookup, "MUST"))
98
	    host_enforce = host_enforce_peername = 1;
99
	else if (!strcasecmp(lookup, "MUST_NOPEERMATCH"))
100
	    host_enforce = 1;
101
	else
102
	    msg_warn("Unknown TLS state for receiving host %s: '%s', using default policy", session->host, lookup);
103
    }
104
    myfree(lookup_key);
105
    lookup_key = lowercase(mystrdup(dest));
106
    if (lookup = maps_find(tls_per_site, dest, 0)) {
107
	if (!strcasecmp(lookup, "NONE"))
108
	    recipient_dont_use = 1;
109
	else if (!strcasecmp(lookup, "MAY"))
110
	    recipient_use = 1;
111
	else if (!strcasecmp(lookup, "MUST"))
112
	    recipient_enforce = recipient_enforce_peername = 1;
113
	else if (!strcasecmp(lookup, "MUST_NOPEERMATCH"))
114
	    recipient_enforce = 1;
115
	else
116
	    msg_warn("Unknown TLS state for recipient domain %s: '%s', using default policy", dest, lookup);
117
    }
118
    myfree(lookup_key);
119
120
    if ((var_smtp_enforce_tls && !host_dont_use && !recipient_dont_use) || host_enforce ||
121
	 recipient_enforce)
122
	session->tls_enforce_tls = session->tls_use_tls = 1;
123
124
    /*
125
     * Set up peername checking. We want to make sure that a MUST* entry in
126
     * the tls_per_site table always has precedence. MUST always must lead to
127
     * a peername check, MUST_NOPEERMATCH must always disable it. Only when
128
     * no explicit setting has been found, the default will be used.
129
     * There is the case left, that both "host" and "recipient" settings
130
     * conflict. In this case, the "host" setting wins.
131
     */
132
    if (host_enforce && host_enforce_peername)
133
	session->tls_enforce_peername = 1;
134
    else if (recipient_enforce && recipient_enforce_peername)
135
	session->tls_enforce_peername = 1;
136
    else if (var_smtp_enforce_tls && var_smtp_tls_enforce_peername)
137
	session->tls_enforce_peername = 1;
138
139
    else if ((var_smtp_use_tls && !host_dont_use && !recipient_dont_use) || host_use || recipient_use)
140
      session->tls_use_tls = 1;
141
#endif
142
    session->tls_info = tls_info_zero;
61
    return (session);
143
    return (session);
62
}
144
}
63
145
Lines 65-70 Link Here
65
147
66
void    smtp_session_free(SMTP_SESSION *session)
148
void    smtp_session_free(SMTP_SESSION *session)
67
{
149
{
150
#ifdef HAS_SSL
151
    vstream_fflush(session->stream);
152
    pfixtls_stop_clienttls(session->stream, var_smtp_starttls_tmout, 0,
153
			   &(session->tls_info));
154
#endif
68
    vstream_fclose(session->stream);
155
    vstream_fclose(session->stream);
69
    myfree(session->host);
156
    myfree(session->host);
70
    myfree(session->addr);
157
    myfree(session->addr);
(-)postfix-1.1.11-20020613-orig/src/smtp/smtp_unalias.c (-1 / +5 lines)
Lines 86-92 Link Here
86
    if ((result = htable_find(cache, name)) == 0) {
86
    if ((result = htable_find(cache, name)) == 0) {
87
	fqdn = vstring_alloc(10);
87
	fqdn = vstring_alloc(10);
88
	if (dns_lookup_types(name, smtp_unalias_flags, (DNS_RR **) 0,
88
	if (dns_lookup_types(name, smtp_unalias_flags, (DNS_RR **) 0,
89
			     fqdn, (VSTRING *) 0, T_MX, T_A, 0) != DNS_OK)
89
			     fqdn, (VSTRING *) 0, T_MX, T_A,
90
#ifdef INET6
91
			     T_AAAA,
92
#endif
93
			     0) != DNS_OK)
90
	    vstring_strcpy(fqdn, name);
94
	    vstring_strcpy(fqdn, name);
91
	htable_enter(cache, name, result = vstring_export(fqdn));
95
	htable_enter(cache, name, result = vstring_export(fqdn));
92
    }
96
    }
(-)postfix-1.1.11-20020613-orig/src/smtpd/Makefile.in (+6 lines)
Lines 134-139 Link Here
134
smtpd.o: ../../include/quote_flags.h
134
smtpd.o: ../../include/quote_flags.h
135
smtpd.o: ../../include/lex_822.h
135
smtpd.o: ../../include/lex_822.h
136
smtpd.o: ../../include/mail_server.h
136
smtpd.o: ../../include/mail_server.h
137
smtpd.o: ../../include/pfixtls.h
137
smtpd.o: smtpd_token.h
138
smtpd.o: smtpd_token.h
138
smtpd.o: smtpd.h
139
smtpd.o: smtpd.h
139
smtpd.o: smtpd_check.h
140
smtpd.o: smtpd_check.h
Lines 162-167 Link Here
162
smtpd_chat.o: ../../include/cleanup_user.h
163
smtpd_chat.o: ../../include/cleanup_user.h
163
smtpd_chat.o: ../../include/mail_error.h
164
smtpd_chat.o: ../../include/mail_error.h
164
smtpd_chat.o: ../../include/name_mask.h
165
smtpd_chat.o: ../../include/name_mask.h
166
smtpd_chat.o: ../../include/pfixtls.h
165
smtpd_chat.o: smtpd.h
167
smtpd_chat.o: smtpd.h
166
smtpd_chat.o: ../../include/mail_stream.h
168
smtpd_chat.o: ../../include/mail_stream.h
167
smtpd_chat.o: smtpd_chat.h
169
smtpd_chat.o: smtpd_chat.h
Lines 197-202 Link Here
197
smtpd_check.o: ../../include/mail_addr_find.h
199
smtpd_check.o: ../../include/mail_addr_find.h
198
smtpd_check.o: ../../include/match_parent_style.h
200
smtpd_check.o: ../../include/match_parent_style.h
199
smtpd_check.o: ../../include/strip_addr.h
201
smtpd_check.o: ../../include/strip_addr.h
202
smtpd_check.o: ../../include/pfixtls.h
200
smtpd_check.o: smtpd.h
203
smtpd_check.o: smtpd.h
201
smtpd_check.o: ../../include/mail_stream.h
204
smtpd_check.o: ../../include/mail_stream.h
202
smtpd_check.o: smtpd_sasl_glue.h
205
smtpd_check.o: smtpd_sasl_glue.h
Lines 213-218 Link Here
213
smtpd_peer.o: ../../include/vstream.h
216
smtpd_peer.o: ../../include/vstream.h
214
smtpd_peer.o: ../../include/argv.h
217
smtpd_peer.o: ../../include/argv.h
215
smtpd_peer.o: ../../include/mail_stream.h
218
smtpd_peer.o: ../../include/mail_stream.h
219
smtpd_peer.o: ../../include/pfixtls.h
216
smtpd_sasl_glue.o: smtpd_sasl_glue.c
220
smtpd_sasl_glue.o: smtpd_sasl_glue.c
217
smtpd_sasl_glue.o: ../../include/sys_defs.h
221
smtpd_sasl_glue.o: ../../include/sys_defs.h
218
smtpd_sasl_glue.o: ../../include/msg.h
222
smtpd_sasl_glue.o: ../../include/msg.h
Lines 266-271 Link Here
266
smtpd_state.o: ../../include/vstring.h
270
smtpd_state.o: ../../include/vstring.h
267
smtpd_state.o: ../../include/argv.h
271
smtpd_state.o: ../../include/argv.h
268
smtpd_state.o: ../../include/mail_stream.h
272
smtpd_state.o: ../../include/mail_stream.h
273
smtpd_state.o: ../../include/pfixtls.h
269
smtpd_state.o: smtpd_chat.h
274
smtpd_state.o: smtpd_chat.h
270
smtpd_state.o: smtpd_sasl_glue.h
275
smtpd_state.o: smtpd_sasl_glue.h
271
smtpd_token.o: smtpd_token.c
276
smtpd_token.o: smtpd_token.c
Lines 275-277 Link Here
275
smtpd_token.o: smtpd_token.h
280
smtpd_token.o: smtpd_token.h
276
smtpd_token.o: ../../include/vstring.h
281
smtpd_token.o: ../../include/vstring.h
277
smtpd_token.o: ../../include/vbuf.h
282
smtpd_token.o: ../../include/vbuf.h
283
smtpd_token.o: ../../include/pfixtls.h
(-)postfix-1.1.11-20020613-orig/src/smtpd/smtpd.c (-6 / +267 lines)
Lines 314-319 Link Here
314
#include <string_list.h>
314
#include <string_list.h>
315
#include <quote_822_local.h>
315
#include <quote_822_local.h>
316
#include <lex_822.h>
316
#include <lex_822.h>
317
#include <pfixtls.h>
317
318
318
/* Single-threaded server skeleton. */
319
/* Single-threaded server skeleton. */
319
320
Lines 338-343 Link Here
338
  */
339
  */
339
int     var_smtpd_rcpt_limit;
340
int     var_smtpd_rcpt_limit;
340
int     var_smtpd_tmout;
341
int     var_smtpd_tmout;
342
char   *var_relay_ccerts;
341
int     var_smtpd_soft_erlim;
343
int     var_smtpd_soft_erlim;
342
int     var_smtpd_hard_erlim;
344
int     var_smtpd_hard_erlim;
343
int     var_queue_minfree;		/* XXX use off_t */
345
int     var_queue_minfree;		/* XXX use off_t */
Lines 385-390 Link Here
385
char   *var_smtpd_noop_cmds;
387
char   *var_smtpd_noop_cmds;
386
char   *var_smtpd_null_key;
388
char   *var_smtpd_null_key;
387
int     var_smtpd_hist_thrsh;
389
int     var_smtpd_hist_thrsh;
390
int     var_smtpd_starttls_tmout;
391
int     var_smtpd_tls_wrappermode;
392
int     var_smtpd_use_tls;
393
int     var_smtpd_enforce_tls;
394
int     var_smtpd_tls_auth_only;
395
int     var_smtpd_tls_ask_ccert;
396
int     var_smtpd_tls_req_ccert;
397
int     var_smtpd_tls_ccert_vd;
398
int     var_smtpd_tls_received_header;
388
399
389
 /*
400
 /*
390
  * Silly little macros.
401
  * Silly little macros.
Lines 489-499 Link Here
489
    if (var_disable_vrfy_cmd == 0)
500
    if (var_disable_vrfy_cmd == 0)
490
	smtpd_chat_reply(state, "250-VRFY");
501
	smtpd_chat_reply(state, "250-VRFY");
491
    smtpd_chat_reply(state, "250-ETRN");
502
    smtpd_chat_reply(state, "250-ETRN");
503
#ifdef HAS_SSL
504
    if ((state->tls_use_tls || state->tls_enforce_tls) && (!state->tls_active))
505
	smtpd_chat_reply(state, "250-STARTTLS");
506
#endif
492
#ifdef USE_SASL_AUTH
507
#ifdef USE_SASL_AUTH
493
    if (var_smtpd_sasl_enable) {
508
    if (var_smtpd_sasl_enable) {
509
#ifdef HAS_SSL
510
      if (!state->tls_auth_only || state->tls_active) {
511
#endif
494
	smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list);
512
	smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list);
495
	if (var_broken_auth_clients)
513
	if (var_broken_auth_clients)
496
	    smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
514
	    smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
515
#ifdef HAS_SSL
516
      }
517
#endif
497
    }
518
    }
498
#endif
519
#endif
499
    smtpd_chat_reply(state, "250-%s", VERP_CMD);
520
    smtpd_chat_reply(state, "250-%s", VERP_CMD);
Lines 918-928 Link Here
918
    state->rcpt_count = 0;
939
    state->rcpt_count = 0;
919
}
940
}
920
941
942
/* CN_sanitize - make sure, the CN-string is well behaved */
943
944
static void CN_sanitize(char *CNstring)
945
{
946
    int i;
947
    int len;
948
    int parencount;
949
950
    /*
951
     * The information included in the CN (CommonName) of the peer and its
952
     * issuer can be included into the Received: header line. The characters
953
     * allowed as well as comment nesting are limited by RFC822.
954
     */
955
956
    len = strlen(CNstring);
957
    /*
958
     * The Received: header can only contain characters. Make sure that only
959
     * acceptable characters are printed. Maybe we could allow more, but
960
     * not everything makes sense inside a CommonName.
961
     */
962
    for (i = 0; i < len; i++) 
963
	if (!((CNstring[i] >= 'A') && (CNstring[i] <='Z')) &&
964
	    !((CNstring[i] >= 'a') && (CNstring[i] <='z')) &&
965
	    !((CNstring[i] >= '0') && (CNstring[i] <='9')) &&
966
	    (CNstring[i] != '(') && (CNstring[i] != ')') &&
967
	    (CNstring[i] != '[') && (CNstring[i] != ']') &&
968
	    (CNstring[i] != '{') && (CNstring[i] != '}') &&
969
	    (CNstring[i] != '<') && (CNstring[i] != '>') &&
970
	    (CNstring[i] != '?') && (CNstring[i] != '!') &&
971
	    (CNstring[i] != ';') && (CNstring[i] != ':') &&
972
	    (CNstring[i] != '"') && (CNstring[i] != '\'') &&
973
	    (CNstring[i] != '/') && (CNstring[i] != '|') &&
974
	    (CNstring[i] != '+') && (CNstring[i] != '&') &&
975
	    (CNstring[i] != '~') && (CNstring[i] != '@') &&
976
	    (CNstring[i] != '#') && (CNstring[i] != '$') &&
977
	    (CNstring[i] != '%') && (CNstring[i] != '&') &&
978
	    (CNstring[i] != '^') && (CNstring[i] != '*') &&
979
	    (CNstring[i] != '_') && (CNstring[i] != '-') &&
980
	    (CNstring[i] != '.') && (CNstring[i] != ' '))
981
	    CNstring[i] = '?';
982
983
    /*
984
     * This information will go into the Received: header inside a comment.
985
     * Since comments can be nested, parentheses '(' and ')' must match.
986
     */
987
    parencount = 0;
988
    for (i = 0; i < len; i++) {
989
	if (CNstring[i] == '(')
990
	    parencount++;
991
	else if (CNstring[i] == ')')
992
	    parencount--;
993
    }
994
    /*
995
     * The necessary condition is violated. Do YOU know, where to correct?
996
     * I don't know, so I will practically remove all parentheses.
997
     */
998
    if (parencount != 0) {
999
	for (i = 0; i < len; i++)
1000
	    if ((CNstring[i] == '(') || (CNstring[i] == ')'))
1001
		CNstring[i] = '/';
1002
    }
1003
}
1004
921
/* data_cmd - process DATA command */
1005
/* data_cmd - process DATA command */
922
1006
923
static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
1007
static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
924
{
1008
{
925
    char   *start;
1009
    char   *start;
1010
    char   *peer_CN;
1011
    char   *issuer_CN;
926
    int     len;
1012
    int     len;
927
    int     curr_rec_type;
1013
    int     curr_rec_type;
928
    int     prev_rec_type;
1014
    int     prev_rec_type;
Lines 961-966 Link Here
961
		"Received: from %s (%s [%s])",
1047
		"Received: from %s (%s [%s])",
962
		state->helo_name ? state->helo_name : state->name,
1048
		state->helo_name ? state->helo_name : state->name,
963
		state->name, state->addr);
1049
		state->name, state->addr);
1050
    if (var_smtpd_tls_received_header && state->tls_active) {
1051
	rec_fprintf(state->cleanup, REC_TYPE_NORM,
1052
		    "\t(using %s with cipher %s (%d/%d bits))",
1053
		    state->tls_info.protocol, state->tls_info.cipher_name,
1054
		    state->tls_info.cipher_usebits,
1055
		    state->tls_info.cipher_algbits);
1056
	if (state->tls_info.peer_CN) {
1057
            peer_CN = mystrdup(state->tls_info.peer_CN);
1058
	    CN_sanitize(peer_CN);
1059
            issuer_CN = mystrdup(state->tls_info.issuer_CN);
1060
	    CN_sanitize(issuer_CN);
1061
	    if (state->tls_info.peer_verified)
1062
		rec_fprintf(state->cleanup, REC_TYPE_NORM,
1063
			"\t(Client CN \"%s\", Issuer \"%s\" (verified OK))",
1064
			peer_CN, issuer_CN);
1065
	    else
1066
		rec_fprintf(state->cleanup, REC_TYPE_NORM,
1067
			"\t(Client CN \"%s\", Issuer \"%s\" (not verified))",
1068
			peer_CN, issuer_CN);
1069
	    myfree(issuer_CN);
1070
	    myfree(peer_CN);
1071
	}
1072
	else if (var_smtpd_tls_ask_ccert)
1073
	    rec_fprintf(state->cleanup, REC_TYPE_NORM,
1074
			"\t(Client did not present a certificate)");
1075
	else
1076
	    rec_fprintf(state->cleanup, REC_TYPE_NORM,
1077
			"\t(No client certificate requested)");
1078
    }
964
    if (state->rcpt_count == 1 && state->recipient) {
1079
    if (state->rcpt_count == 1 && state->recipient) {
965
	rec_fprintf(state->cleanup, REC_TYPE_NORM,
1080
	rec_fprintf(state->cleanup, REC_TYPE_NORM,
966
		    "\tby %s (%s) with %s id %s",
1081
		    "\tby %s (%s) with %s id %s",
Lines 1310-1315 Link Here
1310
    }
1425
    }
1311
}
1426
}
1312
1427
1428
static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
1429
{
1430
    char   *err;
1431
1432
#ifdef HAS_SSL
1433
    if (argc != 1) {
1434
	state->error_mask |= MAIL_ERROR_PROTOCOL;
1435
	smtpd_chat_reply(state, "501 Syntax: STARTTLS");
1436
	return (-1);
1437
    }
1438
    if (state->tls_active != 0) {
1439
	state->error_mask |= MAIL_ERROR_PROTOCOL;
1440
	smtpd_chat_reply(state, "554 Error: TLS already active");
1441
	return (-1);
1442
    }
1443
    if (state->tls_use_tls == 0) {
1444
	state->error_mask |= MAIL_ERROR_PROTOCOL;
1445
	smtpd_chat_reply(state, "502 Error: command not implemented");
1446
	return (-1);
1447
    }
1448
    if (!pfixtls_serverengine) {
1449
	smtpd_chat_reply(state, "454 TLS not available due to temporary reason");
1450
	return (0);
1451
    }
1452
    smtpd_chat_reply(state, "220 Ready to start TLS");
1453
    vstream_fflush(state->client);
1454
    /*
1455
     * When deciding about continuing the handshake, we will stop when a
1456
     * client certificate was _required_ and none was presented or the
1457
     * verification failed. This however does only make sense when TLS is
1458
     * enforced. Otherwise we would happily perform perform the SMTP
1459
     * transaction without any STARTTLS at all! So only have the handshake
1460
     * fail when TLS is also enforced.
1461
     */
1462
    if (pfixtls_start_servertls(state->client, var_smtpd_starttls_tmout,
1463
				state->name, state->addr, &(state->tls_info),
1464
			(var_smtpd_tls_req_ccert && state->tls_enforce_tls))) {
1465
	/*
1466
         * Typically the connection is hanging at this point, so
1467
         * we should try to shut it down by force! Unfortunately this
1468
         * problem is not addressed in postfix!
1469
         */
1470
	return (-1);
1471
    }
1472
    state->tls_active = 1;
1473
    helo_reset(state);
1474
    mail_reset(state);
1475
    rcpt_reset(state);
1476
    return (0);
1477
#else
1478
    state->error_mask |= MAIL_ERROR_PROTOCOL;
1479
    smtpd_chat_reply(state, "502 Error: command not implemented");
1480
    return (-1);
1481
#endif
1482
}
1483
1484
static void tls_reset(SMTPD_STATE *state)
1485
{
1486
    int failure = 0;
1487
1488
    if (state->reason && state->where && strcmp(state->where, SMTPD_AFTER_DOT))
1489
	failure = 1;
1490
#ifdef HAS_SSL
1491
    vstream_fflush(state->client);
1492
    if (state->tls_active)
1493
	pfixtls_stop_servertls(state->client, var_smtpd_starttls_tmout,
1494
			       failure, &(state->tls_info));
1495
#endif
1496
    state->tls_active = 0;
1497
}
1498
1313
 /*
1499
 /*
1314
  * The table of all SMTP commands that we know. Set the junk limit flag on
1500
  * The table of all SMTP commands that we know. Set the junk limit flag on
1315
  * any command that can be repeated an arbitrary number of times without
1501
  * any command that can be repeated an arbitrary number of times without
Lines 1328-1333 Link Here
1328
    "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
1514
    "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
1329
    "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT,
1515
    "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT,
1330
1516
1517
#ifdef HAS_SSL
1518
    "STARTTLS", starttls_cmd, 0,
1519
#endif
1520
1331
#ifdef USE_SASL_AUTH
1521
#ifdef USE_SASL_AUTH
1332
    "AUTH", smtpd_sasl_auth_cmd, 0,
1522
    "AUTH", smtpd_sasl_auth_cmd, 0,
1333
#endif
1523
#endif
Lines 1438-1446 Link Here
1438
		state->error_count++;
1628
		state->error_count++;
1439
		continue;
1629
		continue;
1440
	    }
1630
	    }
1631
	    if (state->tls_enforce_tls &&
1632
		!state->tls_active &&
1633
		cmdp->action != starttls_cmd &&
1634
		cmdp->action != noop_cmd &&
1635
		cmdp->action != ehlo_cmd &&
1636
		cmdp->action != quit_cmd) {
1637
		smtpd_chat_reply(state,
1638
				 "530 Must issue a STARTTLS command first");
1639
		state->error_count++;
1640
		continue;
1641
	    }
1441
	    state->where = cmdp->name;
1642
	    state->where = cmdp->name;
1442
	    if (cmdp->action(state, argc, argv) != 0)
1643
	    if (cmdp->action(state, argc, argv) != 0) {
1443
		state->error_count++;
1644
		state->error_count++;
1645
		/*
1646
		 * Die after TLS negotiation failure, as there is no
1647
		 * stable way to recover from a possible mixture of
1648
		 * TLS and SMTP protocol from the client.
1649
		 */
1650
		if (cmdp->action == starttls_cmd)
1651
		    break;
1652
	    }
1444
	    if ((cmdp->flags & SMTPD_CMD_FLAG_LIMIT)
1653
	    if ((cmdp->flags & SMTPD_CMD_FLAG_LIMIT)
1445
		&& state->junk_cmds++ > var_smtpd_junk_cmd_limit)
1654
		&& state->junk_cmds++ > var_smtpd_junk_cmd_limit)
1446
		state->error_count++;
1655
		state->error_count++;
Lines 1464-1469 Link Here
1464
     * Cleanup whatever information the client gave us during the SMTP
1673
     * Cleanup whatever information the client gave us during the SMTP
1465
     * dialog.
1674
     * dialog.
1466
     */
1675
     */
1676
    tls_reset(state);
1467
    helo_reset(state);
1677
    helo_reset(state);
1468
#ifdef USE_SASL_AUTH
1678
#ifdef USE_SASL_AUTH
1469
    if (var_smtpd_sasl_enable)
1679
    if (var_smtpd_sasl_enable)
Lines 1496-1501 Link Here
1496
     * machines.
1706
     * machines.
1497
     */
1707
     */
1498
    smtpd_state_init(&state, stream);
1708
    smtpd_state_init(&state, stream);
1709
#ifdef HAS_SSL
1710
    if (SMTPD_STAND_ALONE((&state))) {
1711
	state.tls_use_tls = 0;
1712
	state.tls_enforce_tls = 0;
1713
	state.tls_auth_only = 0;
1714
    }
1715
    else {
1716
	state.tls_use_tls = var_smtpd_use_tls | var_smtpd_enforce_tls;
1717
	state.tls_enforce_tls = var_smtpd_enforce_tls;
1718
	if (var_smtpd_tls_wrappermode) {
1719
	    /*
1720
	     * TLS has been set to wrapper mode, meaning that we run on a
1721
	     * seperate port and we must switch to TLS layer before actually
1722
	     * performing the SMTP protocol. This implies enforce-mode.
1723
	     */
1724
	    state.tls_use_tls = state.tls_enforce_tls = 1;
1725
	    if (pfixtls_start_servertls(state.client, var_smtpd_starttls_tmout,
1726
					state.name, state.addr, &state.tls_info,
1727
					var_smtpd_tls_req_ccert)) {
1728
	    /*
1729
	     * Typically the connection is hanging at this point, so
1730
	     * we should try to shut it down by force! Unfortunately this
1731
	     * problem is not addressed in postfix!
1732
	     */
1733
		return;
1734
	    }
1735
	    state.tls_active = 1;
1736
	}
1737
	if (var_smtpd_tls_auth_only || state.tls_enforce_tls)
1738
	    state.tls_auth_only = 1;
1739
    }
1740
#else
1741
    state.tls_use_tls = 0;
1742
    state.tls_enforce_tls = 0;
1743
    state.tls_auth_only = 0;
1744
#endif
1745
1746
    /*
1747
     * Provide the SMTP service.
1748
     */
1499
1749
1500
    /*
1750
    /*
1501
     * See if we need to turn on verbose logging for this client.
1751
     * See if we need to turn on verbose logging for this client.
Lines 1513-1522 Link Here
1513
	smtpd_chat_reply(&state, "220 %s", var_smtpd_banner);
1763
	smtpd_chat_reply(&state, "220 %s", var_smtpd_banner);
1514
	msg_info("connect from %s[%s]", state.name, state.addr);
1764
	msg_info("connect from %s[%s]", state.name, state.addr);
1515
    }
1765
    }
1516
1517
    /*
1518
     * Provide the SMTP service.
1519
     */
1520
    smtpd_proto(&state);
1766
    smtpd_proto(&state);
1521
1767
1522
    /*
1768
    /*
Lines 1542-1548 Link Here
1542
1788
1543
static void pre_jail_init(char *unused_name, char **unused_argv)
1789
static void pre_jail_init(char *unused_name, char **unused_argv)
1544
{
1790
{
1545
1546
    /*
1791
    /*
1547
     * Initialize blacklist/etc. patterns before entering the chroot jail, in
1792
     * Initialize blacklist/etc. patterns before entering the chroot jail, in
1548
     * case they specify a filename pattern.
1793
     * case they specify a filename pattern.
Lines 1558-1563 Link Here
1558
	msg_warn("%s is true, but SASL support is not compiled in",
1803
	msg_warn("%s is true, but SASL support is not compiled in",
1559
		 VAR_SMTPD_SASL_ENABLE);
1804
		 VAR_SMTPD_SASL_ENABLE);
1560
#endif
1805
#endif
1806
1807
#ifdef HAS_SSL
1808
    if (var_smtpd_use_tls || var_smtpd_enforce_tls || var_smtpd_tls_wrappermode)
1809
	pfixtls_init_serverengine(var_smtpd_tls_ccert_vd,
1810
				  var_smtpd_tls_ask_ccert);
1811
#endif
1561
}
1812
}
1562
1813
1563
/* main - the main program */
1814
/* main - the main program */
Lines 1580-1585 Link Here
1580
	VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 0, 0,
1831
	VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 0, 0,
1581
	VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
1832
	VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
1582
	VAR_SMTPD_HIST_THRSH, DEF_SMTPD_HIST_THRSH, &var_smtpd_hist_thrsh, 1, 0,
1833
	VAR_SMTPD_HIST_THRSH, DEF_SMTPD_HIST_THRSH, &var_smtpd_hist_thrsh, 1, 0,
1834
	VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
1583
	0,
1835
	0,
1584
    };
1836
    };
1585
    static CONFIG_TIME_TABLE time_table[] = {
1837
    static CONFIG_TIME_TABLE time_table[] = {
Lines 1595-1600 Link Here
1595
	VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route,
1847
	VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route,
1596
	VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable,
1848
	VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable,
1597
	VAR_BROKEN_AUTH_CLNTS, DEF_BROKEN_AUTH_CLNTS, &var_broken_auth_clients,
1849
	VAR_BROKEN_AUTH_CLNTS, DEF_BROKEN_AUTH_CLNTS, &var_broken_auth_clients,
1850
	VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode,
1851
	VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
1852
	VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
1853
	VAR_SMTPD_TLS_AUTH_ONLY, DEF_SMTPD_TLS_AUTH_ONLY, &var_smtpd_tls_auth_only,
1854
	VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
1855
	VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
1856
	VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header,
1598
	0,
1857
	0,
1599
    };
1858
    };
1600
    static CONFIG_STR_TABLE str_table[] = {
1859
    static CONFIG_STR_TABLE str_table[] = {
Lines 1623-1628 Link Here
1623
	VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0,
1882
	VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0,
1624
	VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0,
1883
	VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0,
1625
	VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0,
1884
	VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0,
1885
	VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_relay_ccerts, 0, 0,
1626
	0,
1886
	0,
1627
    };
1887
    };
1628
1888
Lines 1638-1640 Link Here
1638
		       MAIL_SERVER_PRE_ACCEPT, pre_accept,
1898
		       MAIL_SERVER_PRE_ACCEPT, pre_accept,
1639
		       0);
1899
		       0);
1640
}
1900
}
1901
(-)postfix-1.1.11-20020613-orig/src/smtpd/smtpd.h (+6 lines)
Lines 32-37 Link Here
32
  * Global library.
32
  * Global library.
33
  */
33
  */
34
#include <mail_stream.h>
34
#include <mail_stream.h>
35
#include <pfixtls.h>
35
36
36
 /*
37
 /*
37
  * Variables that keep track of conversation state. There is only one SMTP
38
  * Variables that keep track of conversation state. There is only one SMTP
Lines 81-86 Link Here
81
    VSTRING *sasl_decoded;
82
    VSTRING *sasl_decoded;
82
#endif
83
#endif
83
    int     warn_if_reject;
84
    int     warn_if_reject;
85
    int     tls_active;
86
    int     tls_use_tls;
87
    int     tls_enforce_tls;
88
    int     tls_auth_only;
89
    tls_info_t tls_info;
84
} SMTPD_STATE;
90
} SMTPD_STATE;
85
91
86
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
92
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
(-)postfix-1.1.11-20020613-orig/src/smtpd/smtpd_check.c (-7 / +116 lines)
Lines 280-285 Link Here
280
280
281
#include <namadr_list.h>
281
#include <namadr_list.h>
282
#include <domain_list.h>
282
#include <domain_list.h>
283
#include <string_list.h>
283
#include <mail_params.h>
284
#include <mail_params.h>
284
#include <canon_addr.h>
285
#include <canon_addr.h>
285
#include <resolve_clnt.h>
286
#include <resolve_clnt.h>
Lines 345-350 Link Here
345
static DOMAIN_LIST *relay_domains;
346
static DOMAIN_LIST *relay_domains;
346
static NAMADR_LIST *mynetworks;
347
static NAMADR_LIST *mynetworks;
347
static NAMADR_LIST *perm_mx_networks;
348
static NAMADR_LIST *perm_mx_networks;
349
#ifdef HAS_SSL
350
static MAPS *relay_ccerts;
351
#endif
348
352
349
 /*
353
 /*
350
  * How to do parent domain wildcard matching, if any.
354
  * How to do parent domain wildcard matching, if any.
Lines 530-535 Link Here
530
    perm_mx_networks =
534
    perm_mx_networks =
531
	namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
535
	namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
532
			 var_perm_mx_networks);
536
			 var_perm_mx_networks);
537
#ifdef HAS_SSL
538
    relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_relay_ccerts,
539
			       DICT_FLAG_LOCK);
540
#endif
533
541
534
    /*
542
    /*
535
     * Pre-parse and pre-open the recipient maps.
543
     * Pre-parse and pre-open the recipient maps.
Lines 932-938 Link Here
932
	msg_info("%s: %s", myname, name);
940
	msg_info("%s: %s", myname, name);
933
941
934
    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
942
    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
935
				  (VSTRING *) 0, T_A, T_MX, 0);
943
				  (VSTRING *) 0, T_A, T_MX,
944
#ifdef INET6
945
				  T_AAAA,
946
#endif
947
				  0);
936
    if (dns_status != DNS_OK)
948
    if (dns_status != DNS_OK)
937
	return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
949
	return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
938
				   "%d <%s>: %s rejected: Host not found",
950
				   "%d <%s>: %s rejected: Host not found",
Lines 954-960 Link Here
954
	msg_info("%s: %s", myname, name);
966
	msg_info("%s: %s", myname, name);
955
967
956
    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
968
    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
957
				  (VSTRING *) 0, T_A, T_MX, 0);
969
				  (VSTRING *) 0, T_A, T_MX,
970
#ifdef INET6
971
				  T_AAAA,
972
#endif
973
				  0);
958
    if (dns_status != DNS_OK)
974
    if (dns_status != DNS_OK)
959
	return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
975
	return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
960
				   "%d <%s>: %s rejected: Domain not found",
976
				   "%d <%s>: %s rejected: Domain not found",
Lines 966-971 Link Here
966
982
967
static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
983
static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
968
984
985
/* permit_tls_clientcerts - OK/DUNNO for message relaying */
986
987
#ifdef HAS_SSL
988
static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
989
{
990
    char   *low_name;
991
    const char *found;
992
993
    if (state->tls_info.peer_verified && permit_all_certs) {
994
	if (msg_verbose)
995
	    msg_info("Relaying allowed for all verified client certificates");
996
	return(SMTPD_CHECK_OK);
997
    }
998
999
    if (state->tls_info.peer_verified && state->tls_info.peer_fingerprint) {
1000
	low_name = lowercase(mystrdup(state->tls_info.peer_fingerprint));
1001
	found = maps_find(relay_ccerts, low_name, DICT_FLAG_FIXED);
1002
	myfree(low_name);
1003
	if (found) {
1004
	    if (msg_verbose)
1005
		msg_info("Relaying allowed for certified client: %s", found);
1006
	    return (SMTPD_CHECK_OK);
1007
	} else if (msg_verbose)
1008
	    msg_info("relay_clientcerts: No match for fingerprint '%s'",
1009
		     state->tls_info.peer_fingerprint);
1010
    }
1011
    return (SMTPD_CHECK_DUNNO);
1012
}
1013
#endif
1014
969
/* check_relay_domains - OK/FAIL for message relaying */
1015
/* check_relay_domains - OK/FAIL for message relaying */
970
1016
971
static int check_relay_domains(SMTPD_STATE *state, char *recipient,
1017
static int check_relay_domains(SMTPD_STATE *state, char *recipient,
Lines 1145-1150 Link Here
1145
1191
1146
static int has_my_addr(const char *host)
1192
static int has_my_addr(const char *host)
1147
{
1193
{
1194
#ifdef INET6
1195
    char   *myname = "has_my_addr";
1196
    struct addrinfo hints, *res, *res0;
1197
    int error;
1198
    char hbuf[NI_MAXHOST];
1199
1200
    if (msg_verbose)
1201
	msg_info("%s: host %s", myname, host);
1202
1203
    /*
1204
     * If we can't lookup the host, play safe and assume it is OK.
1205
     */
1206
#define YUP	1
1207
#define NOPE	0
1208
1209
    memset(&hints, 0, sizeof(hints));
1210
    hints.ai_family = PF_UNSPEC;
1211
    hints.ai_socktype = SOCK_DGRAM;
1212
    error = getaddrinfo(host, NULL, &hints, &res0);
1213
    if (error) {
1214
	if (msg_verbose)
1215
	    msg_info("%s: host %s: %s", myname, host, gai_strerror(error));
1216
	return (YUP);
1217
    }
1218
    for (res = res0; res; res = res->ai_next) {
1219
	if (msg_verbose) {
1220
	    if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
1221
		    NULL, 0, NI_NUMERICHOST)) {
1222
		strncpy(hbuf, "???", sizeof(hbuf));
1223
	    }
1224
	    msg_info("%s: addr %s", myname, hbuf);
1225
	}
1226
	if (own_inet_addr(res->ai_addr)) {
1227
	    freeaddrinfo(res0);
1228
	    return (YUP);
1229
	}
1230
    }
1231
    freeaddrinfo(res0);
1232
    if (msg_verbose)
1233
	msg_info("%s: host %s: no match", myname, host);
1234
1235
    return (NOPE);
1236
#else
1148
    char   *myname = "has_my_addr";
1237
    char   *myname = "has_my_addr";
1149
    struct in_addr addr;
1238
    struct in_addr addr;
1150
    char  **cpp;
1239
    char  **cpp;
Lines 1180-1185 Link Here
1180
	msg_info("%s: host %s: no match", myname, host);
1269
	msg_info("%s: host %s: no match", myname, host);
1181
1270
1182
    return (NOPE);
1271
    return (NOPE);
1272
#endif
1183
}
1273
}
1184
1274
1185
/* i_am_mx - is this machine listed as MX relay */
1275
/* i_am_mx - is this machine listed as MX relay */
Lines 1834-1840 Link Here
1834
static int reject_maps_rbl(SMTPD_STATE *state)
1924
static int reject_maps_rbl(SMTPD_STATE *state)
1835
{
1925
{
1836
    char   *myname = "reject_maps_rbl";
1926
    char   *myname = "reject_maps_rbl";
1837
    ARGV   *octets = argv_split(state->addr, ".");
1927
    ARGV   *octets;
1838
    VSTRING *query = vstring_alloc(100);
1928
    VSTRING *query = vstring_alloc(100);
1839
    char   *saved_domains = mystrdup(var_maps_rbl_domains);
1929
    char   *saved_domains = mystrdup(var_maps_rbl_domains);
1840
    char   *bp = saved_domains;
1930
    char   *bp = saved_domains;
Lines 1846-1862 Link Here
1846
    int     dns_status = DNS_FAIL;
1936
    int     dns_status = DNS_FAIL;
1847
    int     i;
1937
    int     i;
1848
    int     result;
1938
    int     result;
1939
    struct  in_addr a;
1849
    VSTRING *why;
1940
    VSTRING *why;
1850
1941
1851
    if (msg_verbose)
1942
    if (msg_verbose)
1852
	msg_info("%s: %s", myname, state->addr);
1943
	msg_info("%s: %s", myname, state->addr);
1853
1944
1854
    /*
1945
#ifndef INET6
1855
     * IPv4 only for now
1946
    /* IPv4 only for now */
1856
     */
1857
#ifdef INET6
1858
    if (inet_pton(AF_INET, state->addr, &a) != 1)
1947
    if (inet_pton(AF_INET, state->addr, &a) != 1)
1859
	return SMTPD_CHECK_DUNNO;
1948
	return SMTPD_CHECK_DUNNO;
1949
    octets = argv_split(state->addr, ".");
1950
#else
1951
    /* IPv4 and IPv6-mapped IPv4 only for now */
1952
    if (inet_pton(AF_INET, state->addr, &a) == 1)
1953
        octets = argv_split(state->addr, ".");
1954
    else {
1955
      struct in6_addr a6;
1956
      if (inet_pton(AF_INET6, state->addr, &a6) != 1)
1957
	  return SMTPD_CHECK_DUNNO;
1958
      if (!IN6_IS_ADDR_V4MAPPED(&a6) || (strrchr(state->addr,':') == NULL))
1959
	  return SMTPD_CHECK_DUNNO;
1960
      octets = argv_split(strrchr(state->addr,':')+1, ".");
1961
    }
1860
#endif
1962
#endif
1861
1963
1862
    /*
1964
    /*
Lines 2154-2159 Link Here
2154
#else
2256
#else
2155
		msg_warn("restriction `%s' ignored: no SASL support", name);
2257
		msg_warn("restriction `%s' ignored: no SASL support", name);
2156
#endif
2258
#endif
2259
#ifdef HAS_SSL
2260
	} else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
2261
	  status = permit_tls_clientcerts(state, 1);
2262
	} else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
2263
	  status = permit_tls_clientcerts(state, 0);
2264
#endif
2157
	} else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
2265
	} else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
2158
	    if (state->recipient)
2266
	    if (state->recipient)
2159
		status = reject_unknown_address(state, state->recipient,
2267
		status = reject_unknown_address(state, state->recipient,
Lines 2588-2593 Link Here
2588
char   *var_rcpt_checks = "";
2696
char   *var_rcpt_checks = "";
2589
char   *var_etrn_checks = "";
2697
char   *var_etrn_checks = "";
2590
char   *var_relay_domains = "";
2698
char   *var_relay_domains = "";
2699
char   *var_relay_ccerts = "";
2591
char   *var_mynetworks = "";
2700
char   *var_mynetworks = "";
2592
char   *var_notify_classes = "";
2701
char   *var_notify_classes = "";
2593
2702
(-)postfix-1.1.11-20020613-orig/src/smtpd/smtpd_peer.c (-26 / +84 lines)
Lines 63-68 Link Here
63
#include <netdb.h>
63
#include <netdb.h>
64
#include <string.h>
64
#include <string.h>
65
65
66
/* Utility library. */
67
68
#include <msg.h>
69
#include <mymalloc.h>
70
#include <valid_hostname.h>
71
#include <stringops.h>
72
73
/* Global library. */
74
66
 /*
75
 /*
67
  * Older systems don't have h_errno. Even modern systems don't have
76
  * Older systems don't have h_errno. Even modern systems don't have
68
  * hstrerror().
77
  * hstrerror().
Lines 84-99 Link Here
84
    )
93
    )
85
#endif
94
#endif
86
95
87
/* Utility library. */
96
#ifdef INET6
88
97
#define GAI_STRERROR(error) \
89
#include <msg.h>
98
	((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
90
#include <mymalloc.h>
99
#endif
91
#include <valid_hostname.h>
100
	
92
#include <stringops.h>
93
94
/* Global library. */
95
96
97
/* Application-specific. */
101
/* Application-specific. */
98
102
99
#include "smtpd.h"
103
#include "smtpd.h"
Lines 102-117 Link Here
102
106
103
void    smtpd_peer_init(SMTPD_STATE *state)
107
void    smtpd_peer_init(SMTPD_STATE *state)
104
{
108
{
105
    struct sockaddr_in sin;
109
#ifdef INET6
106
    SOCKADDR_SIZE len = sizeof(sin);
110
    struct sockaddr_storage ss;
111
#else
112
    struct sockaddr ss;
113
    struct in_addr *in;
107
    struct hostent *hp;
114
    struct hostent *hp;
108
    int     i;
115
#endif
116
    struct sockaddr *sa;
117
    SOCKADDR_SIZE len;
118
119
    sa = (struct sockaddr *)&ss;
120
    len = sizeof(ss);
109
121
110
    /*
122
    /*
111
     * Look up the peer address information.
123
     * Look up the peer address information.
112
     */
124
     */
113
    if (getpeername(vstream_fileno(state->client),
125
    if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) {
114
		    (struct sockaddr *) & sin, &len) >= 0) {
115
	errno = 0;
126
	errno = 0;
116
    }
127
    }
117
128
Lines 127-144 Link Here
127
    /*
138
    /*
128
     * Look up and "verify" the client hostname.
139
     * Look up and "verify" the client hostname.
129
     */
140
     */
130
    else if (errno == 0 && sin.sin_family == AF_INET) {
141
    else if (errno == 0 && (sa->sa_family == AF_INET
131
	state->addr = mystrdup(inet_ntoa(sin.sin_addr));
142
#ifdef INET6
132
	hp = gethostbyaddr((char *) &(sin.sin_addr),
143
			    || sa->sa_family == AF_INET6
133
			   sizeof(sin.sin_addr), AF_INET);
144
#endif
134
	if (hp == 0) {
145
		    )) {
146
#ifdef INET6
147
	char hbuf[NI_MAXHOST];
148
	char abuf[NI_MAXHOST];
149
	struct addrinfo hints, *rnull = NULL;
150
#else
151
	char abuf[sizeof("255.255.255.255") + 1];
152
	char *hbuf;
153
#endif
154
	int error = -1;
155
156
#ifdef INET6
157
	(void)getnameinfo(sa, len, abuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
158
#else
159
	in = &((struct sockaddr_in *)sa)->sin_addr;
160
	inet_ntop(AF_INET, in, abuf, sizeof(hbuf));
161
#endif
162
	state->addr = mystrdup(abuf);
163
#ifdef INET6
164
	error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD);
165
#else
166
	hbuf = NULL;
167
	hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET);
168
	if (hp) {
169
	    error = 0;
170
		hbuf = mystrdup(hp->h_name);
171
	} else
172
	    error = 1;
173
#endif
174
	if (error) {
135
	    state->name = mystrdup("unknown");
175
	    state->name = mystrdup("unknown");
176
#ifdef INET6
177
		state->peer_code = (error == EAI_AGAIN ? 4 : 5);
178
#else
136
	    state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
179
	    state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
137
	} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
180
#endif
181
	} else if (!valid_hostname(hbuf, DONT_GRIPE)) {
138
	    state->name = mystrdup("unknown");
182
	    state->name = mystrdup("unknown");
139
	    state->peer_code = 5;
183
	    state->peer_code = 5;
140
	} else {
184
	} else {
141
	    state->name = mystrdup(hp->h_name);	/* hp->name is clobbered!! */
185
	    state->name = mystrdup(hbuf);	/* hp->name is clobbered!! */
142
	    state->peer_code = 2;
186
	    state->peer_code = 2;
143
187
144
	    /*
188
	    /*
Lines 150-165 Link Here
150
	state->peer_code = code; \
194
	state->peer_code = code; \
151
    }
195
    }
152
196
197
#ifdef INET6
198
	    memset(&hints, 0, sizeof(hints));
199
	    hints.ai_family = AF_UNSPEC;
200
	    hints.ai_socktype = SOCK_STREAM;
201
	    error = getaddrinfo(state->name, NULL, &hints, &rnull);
202
	    if (error) {
203
		msg_warn("%s: hostname %s verification failed: %s",
204
			 state->addr, state->name, GAI_STRERROR(error));
205
		REJECT_PEER_NAME(state, (error == EAI_AGAIN ? 4 : 5));
206
	    }
207
	    /* memcmp() isn't needed if we use getaddrinfo */
208
	    if (rnull)
209
		freeaddrinfo(rnull);
210
#else
153
	    hp = gethostbyname(state->name);	/* clobbers hp->name!! */
211
	    hp = gethostbyname(state->name);	/* clobbers hp->name!! */
154
	    if (hp == 0) {
212
	    if (hp == 0) {
155
		msg_warn("%s: hostname %s verification failed: %s",
213
		msg_warn("%s: hostname %s verification failed: %s",
156
			 state->addr, state->name, HSTRERROR(h_errno));
214
			 state->addr, state->name, HSTRERROR(h_errno));
157
		REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
215
		REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
158
	    } else if (hp->h_length != sizeof(sin.sin_addr)) {
216
	    } else if (hp->h_length != sizeof(*in)) {
159
		msg_warn("%s: hostname %s verification failed: bad address size %d",
217
		msg_warn("%s: hostname %s verification failed: bad address size %d",
160
			 state->addr, state->name, hp->h_length);
218
			 state->addr, state->name, hp->h_length);
161
		REJECT_PEER_NAME(state, 5);
219
		REJECT_PEER_NAME(state, 5);
162
	    } else {
220
	    } else {
221
		int i;
163
		for (i = 0; /* void */ ; i++) {
222
		for (i = 0; /* void */ ; i++) {
164
		    if (hp->h_addr_list[i] == 0) {
223
		    if (hp->h_addr_list[i] == 0) {
165
			msg_warn("%s: address not listed for hostname %s",
224
			msg_warn("%s: address not listed for hostname %s",
Lines 167-178 Link Here
167
			REJECT_PEER_NAME(state, 5);
226
			REJECT_PEER_NAME(state, 5);
168
			break;
227
			break;
169
		    }
228
		    }
170
		    if (memcmp(hp->h_addr_list[i],
229
		    if (memcmp(hp->h_addr_list[i], (char *)in, sizeof(*in)) == 0)
171
			       (char *) &sin.sin_addr,
172
			       sizeof(sin.sin_addr)) == 0)
173
			break;			/* keep peer name */
230
			break;			/* keep peer name */
174
		}
231
		}
175
	    }
232
	    }
233
#endif
176
	}
234
	}
177
    }
235
    }
178
236
(-)postfix-1.1.11-20020613-orig/src/smtpd/smtpd_sasl_proto.c (+7 lines)
Lines 128-133 Link Here
128
	smtpd_chat_reply(state, "503 Error: authentication not enabled");
128
	smtpd_chat_reply(state, "503 Error: authentication not enabled");
129
	return (-1);
129
	return (-1);
130
    }
130
    }
131
#ifdef HAS_SSL
132
    if (state->tls_auth_only && !state->tls_active) {
133
	state->error_mask |= MAIL_ERROR_PROTOCOL;
134
	smtpd_chat_reply(state, "538 Encryption required for requested authentication mechanism");
135
	return (-1);
136
    }
137
#endif
131
    if (state->sasl_username) {
138
    if (state->sasl_username) {
132
	state->error_mask |= MAIL_ERROR_PROTOCOL;
139
	state->error_mask |= MAIL_ERROR_PROTOCOL;
133
	smtpd_chat_reply(state, "503 Error: already authenticated");
140
	smtpd_chat_reply(state, "503 Error: already authenticated");
(-)postfix-1.1.11-20020613-orig/src/smtpd/smtpd_state.c (+5 lines)
Lines 92-97 Link Here
92
    state->msg_size = 0;
92
    state->msg_size = 0;
93
    state->junk_cmds = 0;
93
    state->junk_cmds = 0;
94
    state->warn_if_reject = 0;
94
    state->warn_if_reject = 0;
95
    state->tls_active = 0;
96
    state->tls_use_tls = 0;
97
    state->tls_enforce_tls = 0;
98
    state->tls_info = tls_info_zero;
99
    state->tls_auth_only = 0;
95
100
96
#ifdef USE_SASL_AUTH
101
#ifdef USE_SASL_AUTH
97
    if (SMTPD_STAND_ALONE(state))
102
    if (SMTPD_STAND_ALONE(state))
(-)postfix-1.1.11-20020613-orig/src/smtpstone/smtp-sink.c (-1 / +1 lines)
Lines 518-524 Link Here
518
    } else {
518
    } else {
519
	if (strncmp(argv[optind], "inet:", 5) == 0)
519
	if (strncmp(argv[optind], "inet:", 5) == 0)
520
	    argv[optind] += 5;
520
	    argv[optind] += 5;
521
	sock = inet_listen(argv[optind], backlog, BLOCKING);
521
	sock = inet_listen(argv[optind], backlog, BLOCKING, 1);
522
    }
522
    }
523
523
524
    /*
524
    /*
(-)postfix-1.1.11-20020613-orig/src/tlsmgr/Makefile.in (+75 lines)
Line 0 Link Here
1
SHELL	= /bin/sh
2
SRCS	= tlsmgr.c
3
OBJS	= tlsmgr.o
4
HDRS	=
5
TESTSRC	=
6
WARN	= -W -Wformat -Wimplicit -Wmissing-prototypes \
7
	-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
8
	-Wunused
9
DEFS	= -I. -I$(INC_DIR) -D$(SYSTYPE)
10
CFLAGS	= $(DEBUG) $(OPT) $(DEFS)
11
TESTPROG= 
12
PROG	= tlsmgr
13
INC_DIR	= ../../include
14
LIBS	= ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
15
16
.c.o:;	$(CC) $(CFLAGS) -c $*.c
17
18
$(PROG):	$(OBJS) $(LIBS)
19
	$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
20
21
Makefile: Makefile.in
22
	(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs; cat $?) >$@
23
24
test:	$(TESTPROG)
25
26
update: ../../libexec/$(PROG)
27
28
../../libexec/$(PROG): $(PROG)
29
	cp $(PROG) ../../libexec
30
31
printfck: $(OBJS) $(PROG)
32
	rm -rf printfck
33
	mkdir printfck
34
	cp *.h printfck
35
	sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
36
	set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
37
	cd printfck; make "INC_DIR=../../../../include" `cd ../..; ls *.o`
38
39
lint:
40
	lint $(DEFS) $(SRCS) $(LINTFIX)
41
42
clean:
43
	rm -f *.o *core $(PROG) $(TESTPROG) junk 
44
	rm -rf printfck
45
46
tidy:	clean
47
48
depend: $(MAKES)
49
	(sed '1,/^# do not edit/!d' Makefile.in; \
50
	set -e; for i in [a-z][a-z0-9]*.c; do \
51
	    $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
52
	    -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
53
	done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
54
	@make -f Makefile.in Makefile
55
56
# do not edit below this line - it is generated by 'make depend'
57
tlsmgr.o: tlsmgr.c
58
tlsmgr.o: ../../include/sys_defs.h
59
tlsmgr.o: ../../include/msg.h
60
tlsmgr.o: ../../include/events.h
61
tlsmgr.o: ../../include/vstream.h
62
tlsmgr.o: ../../include/vbuf.h
63
tlsmgr.o: ../../include/dict.h
64
tlsmgr.o: ../../include/argv.h
65
tlsmgr.o: ../../include/vstring.h
66
tlsmgr.o: ../../include/stringops.h
67
tlsmgr.o: ../../include/mymalloc.h
68
tlsmgr.o: ../../include/connect.h
69
tlsmgr.o: ../../include/myflock.h
70
tlsmgr.o: ../../include/mail_conf.h
71
tlsmgr.o: ../../include/mail_params.h
72
tlsmgr.o: ../../include/iostuff.h
73
tlsmgr.o: ../../include/master_proto.h
74
tlsmgr.o: ../../include/mail_server.h
75
tlsmgr.o: ../../include/pfixtls.h
(-)postfix-1.1.11-20020613-orig/src/tlsmgr/tlsmgr.c (+598 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*	tlsmgr 8
4
/* SUMMARY
5
/*	Postfix TLS session cache and PRNG handling manager
6
/* SYNOPSIS
7
/*	\fBtlsmgr\fR [generic Postfix daemon options]
8
/* DESCRIPTION
9
/*	The tlsmgr process does housekeeping on the session cache database
10
/*	files. It runs through the databases and removes expired entries
11
/*	and entries written by older (incompatible) versions.
12
/*
13
/*	The tlsmgr is responsible for the PRNG handling. The used internal
14
/*	OpenSSL PRNG has a pool size of 8192 bits (= 1024 bytes). The pool
15
/*	is initially seeded at startup from an external source (EGD or
16
/*	/dev/urandom) and additional seed is obtained later during program
17
/*	run at a configurable period. The exact time of seed query is
18
/*	using random information and is equally distributed in the range of
19
/*	[0-\fBtls_random_reseed_period\fR] with a \fBtls_random_reseed_period\fR
20
/*	having a default of 1 hour.
21
/*
22
/*	Tlsmgr can be run chrooted and with dropped privileges, as it will
23
/*	connect to the entropy source at startup.
24
/*
25
/*	The PRNG is additionally seeded internally by the data found in the
26
/*	session cache and timevalues.
27
/*
28
/*	Tlsmgr reads the old value of the exchange file at startup to keep
29
/*	entropy already collected during previous runs.
30
/*
31
/*	From the PRNG random pool a cryptographically strong 1024 byte random
32
/*	sequence is written into the PRNG exchange file. The file is updated
33
/*	periodically with the time changing randomly from
34
/*	[0-\fBtls_random_prng_update_period\fR].
35
/* STANDARDS
36
/* SECURITY
37
/* .ad
38
/* .fi
39
/*	Tlsmgr is not security-sensitive. It only deals with external data
40
/*	to be fed into the PRNG, the contents is never trusted. The session
41
/*	cache housekeeping will only remove entries if expired and will never
42
/*	touch the contents of the cached data.
43
/* DIAGNOSTICS
44
/*	Problems and transactions are logged to the syslog daemon.
45
/* BUGS
46
/*	There is no automatic means to limit the number of entries in the
47
/*	session caches and/or the size of the session cache files.
48
/* CONFIGURATION PARAMETERS
49
/* .ad
50
/* .fi
51
/*	The following \fBmain.cf\fR parameters are especially relevant to
52
/*	this program. See the Postfix \fBmain.cf\fR file for syntax details
53
/*	and for default values. Use the \fBpostfix reload\fR command after
54
/*	a configuration change.
55
/* .SH Session Cache
56
/* .ad
57
/* .fi
58
/* .IP \fBsmtpd_tls_session_cache_database\fR
59
/*	Name of the SDBM file (type sdbm:) containing the SMTP server session
60
/*	cache. If the file does not exist, it is created.
61
/* .IP \fBsmtpd_tls_session_cache_timeout\fR
62
/*	Expiry time of SMTP server session cache entries in seconds. Entries
63
/*	older than this are removed from the session cache. A cleanup-run is
64
/*	performed periodically every \fBsmtpd_tls_session_cache_timeout\fR
65
/*	seconds. Default is 3600 (= 1 hour).
66
/* .IP \fBsmtp_tls_session_cache_database\fR
67
/*	Name of the SDBM file (type sdbm:) containing the SMTP client session
68
/*	cache. If the file does not exist, it is created.
69
/* .IP \fBsmtp_tls_session_cache_timeout\fR
70
/*	Expiry time of SMTP client session cache entries in seconds. Entries
71
/*	older than this are removed from the session cache. A cleanup-run is
72
/*	performed periodically every \fBsmtp_tls_session_cache_timeout\fR
73
/*	seconds. Default is 3600 (= 1 hour).
74
/* .SH Pseudo Random Number Generator
75
/* .ad
76
/* .fi
77
/* .IP \fBtls_random_source\fR
78
/*	Name of the EGD socket or device or regular file to obtain entropy
79
/*	from. The type of entropy source must be specified by preceding the
80
/*      name with the appropriate type: egd:/path/to/egd_socket,
81
/*      dev:/path/to/devicefile, or /path/to/regular/file.
82
/*	tlsmgr opens \fBtls_random_source\fR and tries to read
83
/*	\fBtls_random_bytes\fR from it.
84
/* .IP \fBtls_random_bytes\fR
85
/*	Number of bytes to be read from \fBtls_random_source\fR.
86
/*	Default value is 32 bytes. If using EGD, a maximum of 255 bytes is read.
87
/* .IP \fBtls_random_exchange_name\fR
88
/*	Name of the file written by tlsmgr and read by smtp and smtpd at
89
/*	startup. The length is 1024 bytes. Default value is
90
/*	/etc/postfix/prng_exch.
91
/* .IP \fBtls_random_reseed_period\fR
92
/*	Time in seconds until the next reseed from external sources is due.
93
/*	This is the maximum value. The actual point in time is calculated
94
/*	with a random factor equally distributed between 0 and this maximum
95
/*	value. Default is 3600 (= 60 minutes).
96
/* .IP \fBtls_random_prng_update_period\fR
97
/*	Time in seconds until the PRNG exchange file is updated with new
98
/*	pseude random values. This is the maximum value. The actual point
99
/*	in time is calculated with a random factor equally distributed
100
/*	between 0 and this maximum value. Default is 60 (= 1 minute).
101
/* SEE ALSO
102
/*	smtp(8) SMTP client
103
/*	smtpd(8) SMTP server
104
/* LICENSE
105
/* .ad
106
/* .fi
107
/*	The Secure Mailer license must be distributed with this software.
108
/* AUTHOR(S)
109
/*--*/
110
111
/* System library. */
112
113
#include <sys_defs.h>
114
#include <stdlib.h>
115
#include <unistd.h>
116
#include <ctype.h>
117
#include <errno.h>
118
#include <string.h>
119
#include <sys/time.h>			/* gettimeofday, not POSIX */
120
121
/* OpenSSL library. */
122
#ifdef HAS_SSL
123
#include <openssl/rand.h>		/* For the PRNG */
124
#endif
125
126
/* Utility library. */
127
128
#include <msg.h>
129
#include <events.h>
130
#include <dict.h>
131
#include <stringops.h>
132
#include <mymalloc.h>
133
#include <connect.h>
134
#include <myflock.h>
135
136
/* Global library. */
137
138
#include <mail_conf.h>
139
#include <mail_params.h>
140
#include <pfixtls.h>
141
142
/* Master process interface */
143
144
#include <master_proto.h>
145
#include <mail_server.h>
146
147
/* Application-specific. */
148
149
 /*
150
  * Tunables.
151
  */
152
char   *var_tls_rand_source;
153
int	var_tls_rand_bytes;
154
int	var_tls_reseed_period;
155
int	var_tls_prng_upd_period;
156
157
static int rand_exch_fd;
158
static int rand_source_dev_fd = -1;
159
static int rand_source_socket_fd = -1;
160
static int srvr_scache_db_active;
161
static int clnt_scache_db_active;
162
static DICT *srvr_scache_db = NULL;
163
static DICT *clnt_scache_db = NULL;
164
165
static void tlsmgr_prng_upd_event(int unused_event, char *dummy)
166
{
167
    struct timeval tv;
168
    unsigned char buffer[1024];
169
    int next_period;
170
171
#ifdef HAS_SSL
172
    /*
173
     * It is time to update the PRNG exchange file. Since other processes might
174
     * have added entropy, we do this in a read_stir-back_write cycle.
175
     */
176
    GETTIMEOFDAY(&tv);
177
    RAND_seed(&tv, sizeof(struct timeval));
178
179
    if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
180
	msg_fatal("Could not lock random exchange file: %s",
181
		  strerror(errno));
182
183
    lseek(rand_exch_fd, 0, SEEK_SET);
184
    if (read(rand_exch_fd, buffer, 1024) < 0)
185
	msg_fatal("reading exchange file failed");
186
    RAND_seed(buffer, 1024);
187
188
    RAND_bytes(buffer, 1024);
189
    lseek(rand_exch_fd, 0, SEEK_SET);
190
    if (write(rand_exch_fd, buffer, 1024) != 1024)
191
	msg_fatal("Writing exchange file failed");
192
193
    if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
194
	msg_fatal("Could not unlock random exchange file: %s",
195
		  strerror(errno));
196
197
    /*
198
     * Make prediction difficult for outsiders and calculate the time for the
199
     * next execution randomly.
200
     */
201
    next_period = (var_tls_prng_upd_period * buffer[0]) / 255;
202
    event_request_timer(tlsmgr_prng_upd_event, dummy, next_period);
203
#endif
204
}
205
206
207
static void tlsmgr_reseed_event(int unused_event, char *dummy)
208
{
209
    int egd_success;
210
    int next_period;
211
    int rand_bytes;
212
    char buffer[255];
213
    struct timeval tv;
214
    unsigned char randbyte;
215
216
#ifdef HAS_SSL
217
    /*
218
     * It is time to reseed the PRNG.
219
     */
220
221
    GETTIMEOFDAY(&tv);
222
    RAND_seed(&tv, sizeof(struct timeval));
223
    if (rand_source_dev_fd != -1) {
224
	rand_bytes = read(rand_source_dev_fd, buffer, var_tls_rand_bytes);
225
	if (rand_bytes > 0)
226
	    RAND_seed(buffer, rand_bytes);
227
	else if (rand_bytes < 0) {
228
	    msg_fatal("Read from entropy device %s failed",
229
		      var_tls_rand_source);
230
	}
231
    } else if (rand_source_socket_fd != -1) {
232
	egd_success = 0;
233
	buffer[0] = 1;
234
	buffer[1] = var_tls_rand_bytes;
235
	if (write(rand_source_socket_fd, buffer, 2) != 2)
236
	    msg_info("Could not talk to %s", var_tls_rand_source);
237
	else if (read(rand_source_socket_fd, buffer, 1) != 1)
238
	    msg_info("Could not read info from %s", var_tls_rand_source);
239
	else {
240
	    rand_bytes = buffer[0];
241
	    if (read(rand_source_socket_fd, buffer, rand_bytes) != rand_bytes)
242
		msg_info("Could not read data from %s", var_tls_rand_source);
243
	    else {
244
		egd_success = 1;
245
		RAND_seed(buffer, rand_bytes);
246
	    }
247
	}
248
	if (!egd_success) {
249
	    msg_info("Lost connection to EGD-device, exiting to reconnect.");
250
	    exit(0);
251
	}
252
    } else if (*var_tls_rand_source) {
253
	rand_bytes = RAND_load_file(var_tls_rand_source, var_tls_rand_bytes);
254
    }
255
256
    /*
257
     * Make prediction difficult for outsiders and calculate the time for the
258
     * next execution randomly.
259
     */
260
    RAND_bytes(&randbyte, 1);
261
    next_period = (var_tls_reseed_period * randbyte) / 255;
262
    event_request_timer(tlsmgr_reseed_event, dummy, next_period);
263
#endif
264
}
265
266
267
static int tlsmgr_do_scache_check(DICT *scache_db, int scache_timeout,
268
				  int start)
269
{
270
#ifdef HAS_SSL
271
    int func;
272
    int len;
273
    int n;
274
    int delete = 0;
275
    int result;
276
    struct timeval tv;
277
    const char *member;
278
    const char *value;
279
    char *member_copy;
280
    unsigned char nibble, *data;
281
    pfixtls_scache_info_t scache_info;
282
283
    GETTIMEOFDAY(&tv);
284
    RAND_seed(&tv, sizeof(struct timeval));
285
286
    /*
287
     * Run through the given dictionary and check the stored sessions.
288
     * If "start" is set to 1, a new run is initiated, otherwise the next
289
     * item is accessed. The state is internally kept in the DICT.
290
     */
291
    if (start)
292
	func = DICT_SEQ_FUN_FIRST;
293
    else
294
	func = DICT_SEQ_FUN_NEXT;
295
    result = dict_seq(scache_db, func, &member, &value);
296
297
    if (result > 0)
298
	return 0;	/* End of list reached */
299
    else if (result < 0)
300
	msg_fatal("Database fault, should already be caught.");
301
    else {
302
	member_copy = mystrdup(member);
303
	len = strlen(value);
304
	RAND_seed(value, len);		/* Use it to increase entropy */
305
	if (len < 2 * sizeof(pfixtls_scache_info_t))
306
	    delete = 1;		/* Messed up, delete */
307
	else if (len > 2 * sizeof(pfixtls_scache_info_t))
308
	    len = 2 * sizeof(pfixtls_scache_info_t);
309
	if (!delete) {
310
	    data = (unsigned char *)(&scache_info);
311
	    memset(data, 0, len / 2);
312
	    for (n = 0; n < len; n++) {
313
            if ((value[n] >= '0') && (value[n] <= '9'))
314
                nibble = value[n] - '0';
315
            else
316
                nibble = value[n] - 'A' + 10;
317
            if (n % 2)
318
                data[n / 2] |= nibble;
319
            else
320
                data[n / 2] |= (nibble << 4);
321
        }
322
323
        if ((scache_info.scache_db_version != scache_db_version) ||
324
            (scache_info.openssl_version != openssl_version) ||
325
            (scache_info.timestamp + scache_timeout < time(NULL)))
326
	    delete = 1;
327
	}
328
	if (delete)
329
	    result = dict_del(scache_db, member_copy);
330
	myfree(member_copy);
331
    }
332
333
    if (delete && result)
334
	msg_info("Could not delete %s", member);
335
    return 1;
336
337
#else
338
    return 0;
339
#endif
340
}
341
342
static void tlsmgr_clnt_cache_run_event(int unused_event, char *dummy)
343
{
344
345
    /*
346
     * This routine runs when it is time for another tls session cache scan.
347
     * Make sure this routine gets called again in the future.
348
     */
349
    clnt_scache_db_active = tlsmgr_do_scache_check(clnt_scache_db, 
350
				var_smtp_tls_scache_timeout, 1);
351
    event_request_timer(tlsmgr_clnt_cache_run_event, dummy,
352
		 var_smtp_tls_scache_timeout);
353
}
354
355
356
static void tlsmgr_srvr_cache_run_event(int unused_event, char *dummy)
357
{
358
359
    /*
360
     * This routine runs when it is time for another tls session cache scan.
361
     * Make sure this routine gets called again in the future.
362
     */
363
    srvr_scache_db_active = tlsmgr_do_scache_check(srvr_scache_db,
364
				var_smtpd_tls_scache_timeout, 1);
365
    event_request_timer(tlsmgr_srvr_cache_run_event, dummy,
366
		 var_smtpd_tls_scache_timeout);
367
}
368
369
370
static DICT *tlsmgr_cache_open(const char *dbname)
371
{
372
    DICT *retval;
373
    char *dbpagname;
374
    char *dbdirname;
375
376
    /*
377
     * First, try to find out the real name of the database file, so that
378
     * it can be removed.
379
     */
380
    if (!strncmp(dbname, "sdbm:", 5)) {
381
	dbpagname = concatenate(dbname + 5, ".pag", NULL);
382
	REMOVE(dbpagname);
383
	myfree(dbpagname);
384
	dbdirname = concatenate(dbname + 5, ".dir", NULL);
385
	REMOVE(dbdirname);
386
	myfree(dbdirname);
387
    }
388
    else {
389
	msg_warn("Only type sdbm: supported: %s", dbname);
390
	return NULL;
391
    }
392
393
    /*
394
     * Now open the dictionary. Do it with O_EXCL, so that we only open a
395
     * fresh file. If we cannot open it with a fresh file, then we won't
396
     * touch it.
397
     */
398
    retval = dict_open(dbname, O_RDWR | O_CREAT | O_EXCL,
399
	      DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
400
    if (!retval)
401
	msg_warn("Could not create dictionary %s", dbname);
402
    return retval;
403
}
404
405
/* tlsmgr_trigger_event - respond to external trigger(s) */
406
407
static void tlsmgr_trigger_event(char *buf, int len,
408
			               char *unused_service, char **argv)
409
{
410
    /*
411
     * Sanity check. This service takes no command-line arguments.
412
     */
413
    if (argv[0])
414
	msg_fatal("unexpected command-line argument: %s", argv[0]);
415
416
}
417
418
/* tlsmgr_loop - queue manager main loop */
419
420
static int tlsmgr_loop(char *unused_name, char **unused_argv)
421
{
422
    /*
423
     * This routine runs as part of the event handling loop, after the event
424
     * manager has delivered a timer or I/O event (including the completion
425
     * of a connection to a delivery process), or after it has waited for a
426
     * specified amount of time. The result value of qmgr_loop() specifies
427
     * how long the event manager should wait for the next event.
428
     */
429
#define DONT_WAIT	0
430
#define WAIT_FOR_EVENT	(-1)
431
432
    if (clnt_scache_db_active)
433
	clnt_scache_db_active = tlsmgr_do_scache_check(clnt_scache_db,
434
					var_smtp_tls_scache_timeout, 0);
435
    if (srvr_scache_db_active)
436
	srvr_scache_db_active = tlsmgr_do_scache_check(srvr_scache_db,
437
					var_smtpd_tls_scache_timeout, 0);
438
    if (clnt_scache_db_active || srvr_scache_db_active)
439
	return (DONT_WAIT);
440
    return (WAIT_FOR_EVENT);
441
}
442
443
/* pre_accept - see if tables have changed */
444
445
static void pre_accept(char *unused_name, char **unused_argv)
446
{
447
    if (dict_changed()) {
448
	msg_info("table has changed -- exiting");
449
	exit(0);
450
    }
451
}
452
453
/* tlsmgr_pre_init - pre-jail initialization */
454
455
static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
456
{
457
    int rand_bytes;
458
    unsigned char buffer[255];
459
460
#ifdef HAS_SSL
461
    /*
462
     * Access the external sources for random seed. We may not be able to
463
     * access them again if we are sent to chroot jail, so we must leave
464
     * dev: and egd: type sources open.
465
     */
466
    if (*var_tls_rand_source) {
467
        if (!strncmp(var_tls_rand_source, "dev:", 4)) {
468
	    /*
469
	     * Source is a random device
470
	     */
471
	    rand_source_dev_fd = open(var_tls_rand_source + 4, 0, 0);
472
	    if (rand_source_dev_fd == -1) 
473
		msg_fatal("Could not open entropy device %s",
474
			  var_tls_rand_source);
475
	    if (var_tls_rand_bytes > 255)
476
		var_tls_rand_bytes = 255;
477
	    rand_bytes = read(rand_source_dev_fd, buffer, var_tls_rand_bytes);
478
	    RAND_seed(buffer, rand_bytes);
479
	} else if (!strncmp(var_tls_rand_source, "egd:", 4)) {
480
	    /*
481
	     * Source is a EGD compatible socket
482
	     */
483
	    rand_source_socket_fd = unix_connect(var_tls_rand_source +4,
484
						 BLOCKING, 10);
485
	    if (rand_source_socket_fd == -1)
486
		msg_fatal("Could not connect to %s", var_tls_rand_source);
487
	    if (var_tls_rand_bytes > 255)
488
		var_tls_rand_bytes = 255;
489
	    buffer[0] = 1;
490
	    buffer[1] = var_tls_rand_bytes;
491
	    if (write(rand_source_socket_fd, buffer, 2) != 2)
492
		msg_fatal("Could not talk to %s", var_tls_rand_source);
493
	    if (read(rand_source_socket_fd, buffer, 1) != 1)
494
		msg_fatal("Could not read info from %s", var_tls_rand_source);
495
	    rand_bytes = buffer[0];
496
	    if (read(rand_source_socket_fd, buffer, rand_bytes) != rand_bytes)
497
		msg_fatal("Could not read data from %s", var_tls_rand_source);
498
	    RAND_seed(buffer, rand_bytes);
499
	} else {
500
	    rand_bytes = RAND_load_file(var_tls_rand_source,
501
					var_tls_rand_bytes);
502
	}
503
    }
504
#endif
505
506
    /*
507
     * Now open the PRNG exchange file
508
     */
509
    if (*var_tls_rand_exch_name) {
510
	rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
511
    }
512
513
    /*
514
     * Finally, open the session cache files. Remove old files, if still there.
515
     * If we could not remove the old files, something is pretty wrong and we
516
     * won't touch it!!
517
     */
518
    if (*var_smtp_tls_scache_db)
519
	clnt_scache_db = tlsmgr_cache_open(var_smtp_tls_scache_db);
520
    if (*var_smtpd_tls_scache_db)
521
	srvr_scache_db = tlsmgr_cache_open(var_smtpd_tls_scache_db);
522
}
523
524
/* qmgr_post_init - post-jail initialization */
525
526
static void tlsmgr_post_init(char *unused_name, char **unused_argv)
527
{
528
    unsigned char buffer[1024];
529
530
    /*
531
     * This routine runs after the skeleton code has entered the chroot jail.
532
     * Prevent automatic process suicide after a limited number of client
533
     * requests or after a limited amount of idle time.
534
     */
535
    var_use_limit = 0;
536
    var_idle_limit = 0;
537
538
#ifdef HAS_SSL
539
    /*
540
     * Complete thie initialization by reading the additional seed from the
541
     * PRNG exchange file. Don't care how many bytes were actually read, just
542
     * seed buffer into the PRNG, regardless of its contents.
543
     */
544
    if (rand_exch_fd >= 0) {
545
	if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) == -1)
546
	    msg_fatal("Could not lock random exchange file: %s",
547
		      strerror(errno));
548
	read(rand_exch_fd, buffer, 1024);
549
	if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) == -1)
550
	    msg_fatal("Could not unlock random exchange file: %s",
551
		      strerror(errno));
552
	RAND_seed(buffer, 1024);
553
	tlsmgr_prng_upd_event(0, (char *) 0);
554
	tlsmgr_reseed_event(0, (char *) 0);
555
    }
556
#endif
557
558
    clnt_scache_db_active = 0;
559
    srvr_scache_db_active = 0;
560
    if (clnt_scache_db)
561
	tlsmgr_clnt_cache_run_event(0, (char *) 0);
562
    if (srvr_scache_db)
563
	tlsmgr_srvr_cache_run_event(0, (char *) 0);
564
}
565
566
/* main - the main program */
567
568
int     main(int argc, char **argv)
569
{
570
    static CONFIG_STR_TABLE str_table[] = {
571
	VAR_TLS_RAND_SOURCE, DEF_TLS_RAND_SOURCE, &var_tls_rand_source, 0, 0,
572
	0,
573
    };
574
    static CONFIG_TIME_TABLE time_table[] = {
575
	VAR_TLS_RESEED_PERIOD, DEF_TLS_RESEED_PERIOD, &var_tls_reseed_period, 0, 0,
576
	VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_upd_period, 0, 0,
577
	0,
578
    };
579
    static CONFIG_INT_TABLE int_table[] = {
580
	VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 0, 0,
581
	0,
582
    };
583
584
    /*
585
     * Use the trigger service skeleton, because no-one else should be
586
     * monitoring our service port while this process runs, and because we do
587
     * not talk back to the client.
588
     */
589
    trigger_server_main(argc, argv, tlsmgr_trigger_event,
590
			MAIL_SERVER_TIME_TABLE, time_table,
591
			MAIL_SERVER_INT_TABLE, int_table,
592
			MAIL_SERVER_STR_TABLE, str_table,
593
			MAIL_SERVER_PRE_INIT, tlsmgr_pre_init,
594
			MAIL_SERVER_POST_INIT, tlsmgr_post_init,
595
			MAIL_SERVER_LOOP, tlsmgr_loop,
596
			MAIL_SERVER_PRE_ACCEPT, pre_accept,
597
			0);
598
}
(-)postfix-1.1.11-20020613-orig/src/util/Makefile.in (-6 / +15 lines)
Lines 8-14 Link Here
8
	dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \
8
	dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \
9
	environ.c events.c exec_command.c fifo_listen.c fifo_trigger.c \
9
	environ.c events.c exec_command.c fifo_listen.c fifo_trigger.c \
10
	file_limit.c find_inet.c fsspace.c fullname.c get_domainname.c \
10
	file_limit.c find_inet.c fsspace.c fullname.c get_domainname.c \
11
	get_hostname.c hex_quote.c htable.c inet_addr_host.c \
11
	get_hostname.c get_port.c hex_quote.c htable.c inet_addr_host.c \
12
	inet_addr_list.c inet_addr_local.c inet_connect.c inet_listen.c \
12
	inet_addr_list.c inet_addr_local.c inet_connect.c inet_listen.c \
13
	inet_trigger.c inet_util.c intv.c line_wrap.c lowercase.c \
13
	inet_trigger.c inet_util.c intv.c line_wrap.c lowercase.c \
14
	lstat_as.c mac_expand.c mac_parse.c make_dirs.c match_list.c \
14
	lstat_as.c mac_expand.c mac_parse.c make_dirs.c match_list.c \
Lines 26-32 Link Here
26
	unix_connect.c unix_listen.c unix_trigger.c unsafe.c username.c \
26
	unix_connect.c unix_listen.c unix_trigger.c unsafe.c username.c \
27
	valid_hostname.c vbuf.c vbuf_print.c vstream.c vstream_popen.c \
27
	valid_hostname.c vbuf.c vbuf_print.c vstream.c vstream_popen.c \
28
	vstring.c vstring_vstream.c watchdog.c writable.c write_buf.c \
28
	vstring.c vstring_vstream.c watchdog.c writable.c write_buf.c \
29
	write_wait.c strcasecmp.c nvtable.c
29
	write_wait.c strcasecmp.c nvtable.c dict_sdbm.c sdbm.c
30
OBJS	= alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
30
OBJS	= alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
31
	attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
31
	attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
32
	chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
32
	chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
Lines 36-42 Link Here
36
	dict_tcp.o dict_unix.o dir_forest.o doze.o duplex_pipe.o \
36
	dict_tcp.o dict_unix.o dir_forest.o doze.o duplex_pipe.o \
37
	environ.o events.o exec_command.o fifo_listen.o fifo_trigger.o \
37
	environ.o events.o exec_command.o fifo_listen.o fifo_trigger.o \
38
	file_limit.o find_inet.o fsspace.o fullname.o get_domainname.o \
38
	file_limit.o find_inet.o fsspace.o fullname.o get_domainname.o \
39
	get_hostname.o hex_quote.o htable.o inet_addr_host.o \
39
	get_hostname.o get_port.o hex_quote.o htable.o inet_addr_host.o \
40
	inet_addr_list.o inet_addr_local.o inet_connect.o inet_listen.o \
40
	inet_addr_list.o inet_addr_local.o inet_connect.o inet_listen.o \
41
	inet_trigger.o inet_util.o intv.o line_wrap.o lowercase.o \
41
	inet_trigger.o inet_util.o intv.o line_wrap.o lowercase.o \
42
	lstat_as.o mac_expand.o mac_parse.o make_dirs.o match_list.o \
42
	lstat_as.o mac_expand.o mac_parse.o make_dirs.o match_list.o \
Lines 54-66 Link Here
54
	unix_connect.o unix_listen.o unix_trigger.o unsafe.o username.o \
54
	unix_connect.o unix_listen.o unix_trigger.o unsafe.o username.o \
55
	valid_hostname.o vbuf.o vbuf_print.o vstream.o vstream_popen.o \
55
	valid_hostname.o vbuf.o vbuf_print.o vstream.o vstream_popen.o \
56
	vstring.o vstring_vstream.o watchdog.o writable.o write_buf.o \
56
	vstring.o vstring_vstream.o watchdog.o writable.o write_buf.o \
57
	write_wait.o nvtable.o $(STRCASE)
57
	write_wait.o nvtable.o $(STRCASE) dict_sdbm.o sdbm.o
58
HDRS	= argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
58
HDRS	= argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
59
	connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
59
	connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
60
	dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
60
	dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
61
	dict_nisplus.h dict_pcre.h dict_regexp.h dict_static.h dict_tcp.h \
61
	dict_nisplus.h dict_pcre.h dict_regexp.h dict_static.h dict_tcp.h \
62
	dict_unix.h dir_forest.h events.h exec_command.h find_inet.h \
62
	dict_unix.h dir_forest.h events.h exec_command.h find_inet.h \
63
	fsspace.h fullname.h get_domainname.h get_hostname.h hex_quote.h \
63
	fsspace.h fullname.h get_domainname.h get_hostname.h get_port.h hex_quote.h \
64
	htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \
64
	htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \
65
	inet_util.h intv.h iostuff.h line_wrap.h listen.h lstat_as.h \
65
	inet_util.h intv.h iostuff.h line_wrap.h listen.h lstat_as.h \
66
	mac_expand.h mac_parse.h make_dirs.h match_list.h match_ops.h \
66
	mac_expand.h mac_parse.h make_dirs.h match_list.h match_ops.h \
Lines 72-78 Link Here
72
	split_at.h stat_as.h stringops.h sys_defs.h timed_connect.h \
72
	split_at.h stat_as.h stringops.h sys_defs.h timed_connect.h \
73
	timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \
73
	timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \
74
	vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \
74
	vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \
75
	nvtable.h
75
	nvtable.h dict_sdbm.h sdbm.h
76
TESTSRC	= fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
76
TESTSRC	= fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
77
	stream_test.c dup2_pass_on_exec.c
77
	stream_test.c dup2_pass_on_exec.c
78
WARN	= -W -Wformat -Wimplicit -Wmissing-prototypes \
78
WARN	= -W -Wformat -Wimplicit -Wmissing-prototypes \
Lines 591-596 Link Here
591
dict_open.o: dict_unix.h
591
dict_open.o: dict_unix.h
592
dict_open.o: dict_tcp.h
592
dict_open.o: dict_tcp.h
593
dict_open.o: dict_dbm.h
593
dict_open.o: dict_dbm.h
594
dict_open.o: dict_sdbm.h
594
dict_open.o: dict_db.h
595
dict_open.o: dict_db.h
595
dict_open.o: dict_nis.h
596
dict_open.o: dict_nis.h
596
dict_open.o: dict_nisplus.h
597
dict_open.o: dict_nisplus.h
Lines 725-730 Link Here
725
get_domainname.o: mymalloc.h
726
get_domainname.o: mymalloc.h
726
get_domainname.o: get_hostname.h
727
get_domainname.o: get_hostname.h
727
get_domainname.o: get_domainname.h
728
get_domainname.o: get_domainname.h
729
get_port.o: sys_defs.h
728
get_hostname.o: get_hostname.c
730
get_hostname.o: get_hostname.c
729
get_hostname.o: sys_defs.h
731
get_hostname.o: sys_defs.h
730
get_hostname.o: mymalloc.h
732
get_hostname.o: mymalloc.h
Lines 841-846 Link Here
841
match_list.o: stringops.h
843
match_list.o: stringops.h
842
match_list.o: argv.h
844
match_list.o: argv.h
843
match_list.o: dict.h
845
match_list.o: dict.h
846
match_list.o: inet_util.h
844
match_list.o: match_ops.h
847
match_list.o: match_ops.h
845
match_list.o: match_list.h
848
match_list.o: match_list.h
846
match_ops.o: match_ops.c
849
match_ops.o: match_ops.c
Lines 1225-1227 Link Here
1225
write_wait.o: sys_defs.h
1228
write_wait.o: sys_defs.h
1226
write_wait.o: msg.h
1229
write_wait.o: msg.h
1227
write_wait.o: iostuff.h
1230
write_wait.o: iostuff.h
1231
sdbm.o: sdbm.c
1232
sdbm.o: sdbm.h
1233
dict_sdbm.o: sdbm.h
1234
dict_sdbm.o: dict_sdbm.c
1235
dict_sdbm.o: dict_sdbm.h
1236
dict_sdbm.o: sys_defs.h
(-)postfix-1.1.11-20020613-orig/src/util/dict_open.c (+2 lines)
Lines 159-164 Link Here
159
#include <dict_env.h>
159
#include <dict_env.h>
160
#include <dict_unix.h>
160
#include <dict_unix.h>
161
#include <dict_tcp.h>
161
#include <dict_tcp.h>
162
#include <dict_sdbm.h>
162
#include <dict_dbm.h>
163
#include <dict_dbm.h>
163
#include <dict_db.h>
164
#include <dict_db.h>
164
#include <dict_nis.h>
165
#include <dict_nis.h>
Lines 187-192 Link Here
187
#if 0
188
#if 0
188
    DICT_TYPE_TCP, dict_tcp_open,
189
    DICT_TYPE_TCP, dict_tcp_open,
189
#endif
190
#endif
191
    "sdbm", dict_sdbm_open,
190
#ifdef HAS_DBM
192
#ifdef HAS_DBM
191
    DICT_TYPE_DBM, dict_dbm_open,
193
    DICT_TYPE_DBM, dict_dbm_open,
192
#endif
194
#endif
(-)postfix-1.1.11-20020613-orig/src/util/dict_sdbm.c (+408 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*	dict_sdbm 3
4
/* SUMMARY
5
/*	dictionary manager interface to SDBM files
6
/* SYNOPSIS
7
/*	#include <dict_sdbm.h>
8
/*
9
/*	DICT	*dict_sdbm_open(path, open_flags, dict_flags)
10
/*	const char *name;
11
/*	const char *path;
12
/*	int	open_flags;
13
/*	int	dict_flags;
14
/* DESCRIPTION
15
/*	dict_sdbm_open() opens the named SDBM database and makes it available
16
/*	via the generic interface described in dict_open(3).
17
/* DIAGNOSTICS
18
/*	Fatal errors: cannot open file, file write error, out of memory.
19
/* SEE ALSO
20
/*	dict(3) generic dictionary manager
21
/*	sdbm(3) data base subroutines
22
/* LICENSE
23
/* .ad
24
/* .fi
25
/*	The Secure Mailer license must be distributed with this software.
26
/* AUTHOR(S)
27
/*	Wietse Venema
28
/*	IBM T.J. Watson Research
29
/*	P.O. Box 704
30
/*	Yorktown Heights, NY 10598, USA
31
/*--*/
32
33
#include "sys_defs.h"
34
35
/* System library. */
36
37
#include <sys/stat.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
/* Utility library. */
42
43
#include "msg.h"
44
#include "mymalloc.h"
45
#include "htable.h"
46
#include "iostuff.h"
47
#include "vstring.h"
48
#include "myflock.h"
49
#include "stringops.h"
50
#include "dict.h"
51
#include "dict_sdbm.h"
52
#include "sdbm.h"
53
54
/* Application-specific. */
55
56
typedef struct {
57
    DICT    dict;			/* generic members */
58
    SDBM   *dbm;			/* open database */
59
    char   *path;			/* pathname */
60
} DICT_SDBM;
61
62
/* dict_sdbm_lookup - find database entry */
63
64
static const char *dict_sdbm_lookup(DICT *dict, const char *name)
65
{
66
    DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
67
    datum   dbm_key;
68
    datum   dbm_value;
69
    static VSTRING *buf;
70
    const char *result = 0;
71
72
    dict_errno = 0;
73
74
    /*
75
     * Acquire an exclusive lock.
76
     */
77
    if ((dict->flags & DICT_FLAG_LOCK)
78
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
79
	msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
80
81
    /*
82
     * See if this DBM file was written with one null byte appended to key
83
     * and value.
84
     */
85
    if (dict->flags & DICT_FLAG_TRY1NULL) {
86
	dbm_key.dptr = (void *) name;
87
	dbm_key.dsize = strlen(name) + 1;
88
	dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
89
	if (dbm_value.dptr != 0) {
90
	    dict->flags &= ~DICT_FLAG_TRY0NULL;
91
	    result = dbm_value.dptr;
92
	}
93
    }
94
95
    /*
96
     * See if this DBM file was written with no null byte appended to key and
97
     * value.
98
     */
99
    if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
100
	dbm_key.dptr = (void *) name;
101
	dbm_key.dsize = strlen(name);
102
	dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
103
	if (dbm_value.dptr != 0) {
104
	    if (buf == 0)
105
		buf = vstring_alloc(10);
106
	    vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize);
107
	    dict->flags &= ~DICT_FLAG_TRY1NULL;
108
	    result = vstring_str(buf);
109
	}
110
    }
111
112
    /*
113
     * Release the exclusive lock.
114
     */
115
    if ((dict->flags & DICT_FLAG_LOCK)
116
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
117
	msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
118
119
    return (result);
120
}
121
122
/* dict_sdbm_update - add or update database entry */
123
124
static void dict_sdbm_update(DICT *dict, const char *name, const char *value)
125
{
126
    DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
127
    datum   dbm_key;
128
    datum   dbm_value;
129
    int     status;
130
131
    dbm_key.dptr = (void *) name;
132
    dbm_value.dptr = (void *) value;
133
    dbm_key.dsize = strlen(name);
134
    dbm_value.dsize = strlen(value);
135
136
    /*
137
     * If undecided about appending a null byte to key and value, choose a
138
     * default depending on the platform.
139
     */
140
    if ((dict->flags & DICT_FLAG_TRY1NULL)
141
	&& (dict->flags & DICT_FLAG_TRY0NULL)) {
142
#ifdef DBM_NO_TRAILING_NULL
143
	dict->flags &= ~DICT_FLAG_TRY1NULL;
144
#else
145
	dict->flags &= ~DICT_FLAG_TRY0NULL;
146
#endif
147
    }
148
149
    /*
150
     * Optionally append a null byte to key and value.
151
     */
152
    if (dict->flags & DICT_FLAG_TRY1NULL) {
153
	dbm_key.dsize++;
154
	dbm_value.dsize++;
155
    }
156
157
    /*
158
     * Acquire an exclusive lock.
159
     */
160
    if ((dict->flags & DICT_FLAG_LOCK)
161
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
162
	msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
163
164
    /*
165
     * Do the update.
166
     */
167
    if ((status = sdbm_store(dict_sdbm->dbm, dbm_key, dbm_value,
168
     (dict->flags & DICT_FLAG_DUP_REPLACE) ? DBM_REPLACE : DBM_INSERT)) < 0)
169
	msg_fatal("error writing SDBM database %s: %m", dict_sdbm->path);
170
    if (status) {
171
	if (dict->flags & DICT_FLAG_DUP_IGNORE)
172
	     /* void */ ;
173
	else if (dict->flags & DICT_FLAG_DUP_WARN)
174
	    msg_warn("%s: duplicate entry: \"%s\"", dict_sdbm->path, name);
175
	else
176
	    msg_fatal("%s: duplicate entry: \"%s\"", dict_sdbm->path, name);
177
    }
178
179
    /*
180
     * Release the exclusive lock.
181
     */
182
    if ((dict->flags & DICT_FLAG_LOCK)
183
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
184
	msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
185
}
186
187
188
/* dict_sdbm_delete - delete one entry from the dictionary */
189
190
static int dict_sdbm_delete(DICT *dict, const char *name)
191
{
192
    DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
193
    datum   dbm_key;
194
    int     status = 1;
195
    int     flags = 0;
196
197
    /*
198
     * Acquire an exclusive lock.
199
     */
200
    if ((dict->flags & DICT_FLAG_LOCK)
201
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
202
	msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
203
204
    /*
205
     * See if this DBM file was written with one null byte appended to key
206
     * and value.
207
     */
208
    if (dict->flags & DICT_FLAG_TRY1NULL) {
209
	dbm_key.dptr = (void *) name;
210
	dbm_key.dsize = strlen(name) + 1;
211
	sdbm_clearerr(dict_sdbm->dbm);
212
	if ((status = sdbm_delete(dict_sdbm->dbm, dbm_key)) < 0) {
213
	    if (sdbm_error(dict_sdbm->dbm) != 0)	/* fatal error */
214
		msg_fatal("error deleting from %s: %m", dict_sdbm->path);
215
	    status = 1;				/* not found */
216
	} else {
217
	    dict->flags &= ~DICT_FLAG_TRY0NULL;	/* found */
218
	}
219
    }
220
221
    /*
222
     * See if this DBM file was written with no null byte appended to key and
223
     * value.
224
     */
225
    if (status > 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
226
	dbm_key.dptr = (void *) name;
227
	dbm_key.dsize = strlen(name);
228
	sdbm_clearerr(dict_sdbm->dbm);
229
	if ((status = sdbm_delete(dict_sdbm->dbm, dbm_key)) < 0) {
230
	    if (sdbm_error(dict_sdbm->dbm) != 0)	/* fatal error */
231
		msg_fatal("error deleting from %s: %m", dict_sdbm->path);
232
	    status = 1;				/* not found */
233
	} else {
234
	    dict->flags &= ~DICT_FLAG_TRY1NULL;	/* found */
235
	}
236
    }
237
238
    /*
239
     * Release the exclusive lock.
240
     */
241
    if ((dict->flags & DICT_FLAG_LOCK)
242
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
243
	msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
244
245
    return (status);
246
}
247
248
/* traverse the dictionary */
249
250
static int dict_sdbm_sequence(DICT *dict, const int function,
251
			             const char **key, const char **value)
252
{
253
    char   *myname = "dict_sdbm_sequence";
254
    DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
255
    datum   dbm_key;
256
    datum   dbm_value;
257
    int     status = 0;
258
    static VSTRING *key_buf;
259
    static VSTRING *value_buf;
260
261
    /*
262
     * Acquire an exclusive lock.
263
     */
264
    if ((dict->flags & DICT_FLAG_LOCK)
265
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
266
	msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
267
268
    /*
269
     * Determine and execute the seek function. It returns the key.
270
     */
271
    switch (function) {
272
    case DICT_SEQ_FUN_FIRST:
273
	dbm_key = sdbm_firstkey(dict_sdbm->dbm);
274
	break;
275
    case DICT_SEQ_FUN_NEXT:
276
	dbm_key = sdbm_nextkey(dict_sdbm->dbm);
277
	break;
278
    default:
279
	msg_panic("%s: invalid function: %d", myname, function);
280
    }
281
282
    /*
283
     * Release the exclusive lock.
284
     */
285
    if ((dict->flags & DICT_FLAG_LOCK)
286
	&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
287
	msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
288
289
    if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
290
291
	/*
292
	 * See if this DB file was written with one null byte appended to key
293
	 * an d value or not. If necessary, copy the key.
294
	 */
295
	if (((char *) dbm_key.dptr)[dbm_key.dsize - 1] == 0) {
296
	    *key = dbm_key.dptr;
297
	} else {
298
	    if (key_buf == 0)
299
		key_buf = vstring_alloc(10);
300
	    vstring_strncpy(key_buf, dbm_key.dptr, dbm_key.dsize);
301
	    *key = vstring_str(key_buf);
302
	}
303
304
	/*
305
	 * Fetch the corresponding value.
306
	 */
307
	dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
308
309
	if (dbm_value.dptr != 0 && dbm_value.dsize > 0) {
310
311
	    /*
312
	     * See if this DB file was written with one null byte appended to
313
	     * key and value or not. If necessary, copy the key.
314
	     */
315
	    if (((char *) dbm_value.dptr)[dbm_value.dsize - 1] == 0) {
316
		*value = dbm_value.dptr;
317
	    } else {
318
		if (value_buf == 0)
319
		    value_buf = vstring_alloc(10);
320
		vstring_strncpy(value_buf, dbm_value.dptr, dbm_value.dsize);
321
		*value = vstring_str(value_buf);
322
	    }
323
	} else {
324
325
	    /*
326
	     * Determine if we have hit the last record or an error
327
	     * condition.
328
	     */
329
	    if (sdbm_error(dict_sdbm->dbm))
330
		msg_fatal("error seeking %s: %m", dict_sdbm->path);
331
	    return (1);				/* no error: eof/not found
332
						 * (should not happen!) */
333
	}
334
    } else {
335
336
	/*
337
	 * Determine if we have hit the last record or an error condition.
338
	 */
339
	if (sdbm_error(dict_sdbm->dbm))
340
	    msg_fatal("error seeking %s: %m", dict_sdbm->path);
341
	return (1);				/* no error: eof/not found */
342
    }
343
    return (0);
344
}
345
346
/* dict_sdbm_close - disassociate from data base */
347
348
static void dict_sdbm_close(DICT *dict)
349
{
350
    DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
351
352
    sdbm_close(dict_sdbm->dbm);
353
    myfree(dict_sdbm->path);
354
    myfree((char *) dict_sdbm);
355
}
356
357
/* dict_sdbm_open - open SDBM data base */
358
359
DICT   *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
360
{
361
    DICT_SDBM *dict_sdbm;
362
    struct stat st;
363
    SDBM   *dbm;
364
    char   *dbm_path;
365
    int     lock_fd;
366
367
    if (dict_flags & DICT_FLAG_LOCK) {
368
	dbm_path = concatenate(path, ".pag", (char *) 0);
369
	if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
370
	    msg_fatal("open database %s: %m", dbm_path);
371
	if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
372
	    msg_fatal("shared-lock database %s for open: %m", dbm_path);
373
    }
374
375
    /*
376
     * XXX SunOS 5.x has no const in dbm_open() prototype.
377
     */
378
    if ((dbm = sdbm_open((char *) path, open_flags, 0644)) == 0)
379
	msg_fatal("open database %s.{dir,pag}: %m", path);
380
381
    if (dict_flags & DICT_FLAG_LOCK) {
382
	if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
383
	    msg_fatal("unlock database %s for open: %m", dbm_path);
384
	if (close(lock_fd) < 0)
385
	    msg_fatal("close database %s: %m", dbm_path);
386
	myfree(dbm_path);
387
    }
388
    dict_sdbm = (DICT_SDBM *) mymalloc(sizeof(*dict_sdbm));
389
    dict_sdbm->dict.lookup = dict_sdbm_lookup;
390
    dict_sdbm->dict.update = dict_sdbm_update;
391
    dict_sdbm->dict.delete = dict_sdbm_delete;
392
    dict_sdbm->dict.sequence = dict_sdbm_sequence;
393
    dict_sdbm->dict.close = dict_sdbm_close;
394
    dict_sdbm->dict.lock_fd = sdbm_dirfno(dbm);
395
    dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm);
396
    if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
397
	msg_fatal("dict_sdbm_open: fstat: %m");
398
    dict_sdbm->dict.mtime = st.st_mtime;
399
    close_on_exec(sdbm_pagfno(dbm), CLOSE_ON_EXEC);
400
    close_on_exec(sdbm_dirfno(dbm), CLOSE_ON_EXEC);
401
    dict_sdbm->dict.flags = dict_flags | DICT_FLAG_FIXED;
402
    if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
403
	dict_sdbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
404
    dict_sdbm->dbm = dbm;
405
    dict_sdbm->path = mystrdup(path);
406
407
    return (&dict_sdbm->dict);
408
}
(-)postfix-1.1.11-20020613-orig/src/util/dict_sdbm.h (+35 lines)
Line 0 Link Here
1
#ifndef _DICT_SDBM_H_INCLUDED_
2
#define _DICT_SDBM_H_INCLUDED_
3
4
/*++
5
/* NAME
6
/*	dict_dbm 3h
7
/* SUMMARY
8
/*	dictionary manager interface to DBM files
9
/* SYNOPSIS
10
/*	#include <dict_dbm.h>
11
/* DESCRIPTION
12
/* .nf
13
14
 /*
15
  * Utility library.
16
  */
17
#include <dict.h>
18
19
 /*
20
  * External interface.
21
  */
22
extern DICT *dict_sdbm_open(const char *, int, int);
23
24
/* LICENSE
25
/* .ad
26
/* .fi
27
/*	The Secure Mailer license must be distributed with this software.
28
/* AUTHOR(S)
29
/*	Wietse Venema
30
/*	IBM T.J. Watson Research
31
/*	P.O. Box 704
32
/*	Yorktown Heights, NY 10598, USA
33
/*--*/
34
35
#endif
(-)postfix-1.1.11-20020613-orig/src/util/get_port.c (+65 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*	get_port 3
4
/* SUMMARY
5
/*	trivial host and port extracter
6
/* SYNOPSIS
7
/*	#include <get_port.h>
8
/*
9
/*	char	*get_port(data)
10
/*	char	*data;
11
/*
12
/* DESCRIPTION
13
/* 	get_port() extract host name or ip address from
14
/* 	strings such as [3ffe:902:12::10]:25, [::1]
15
/* 	or 192.168.0.1:25, and null-terminates the
16
/* 	\fIdata\fR at the first occurrence of port separator.
17
/* DIAGNOSTICS
18
/* 	If port not found return null pointer.
19
/* LICENSE
20
/* .ad
21
/* .fi
22
/*	BSD Style (or BSD like) license.
23
/* AUTHOR(S)
24
/*	Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
25
/*	Wroclaw, POLAND
26
/*--*/
27
28
/* System libraries */
29
30
#include <sys_defs.h>
31
#include <string.h>
32
33
/* Utility library. */
34
35
#include "get_port.h"
36
37
/* get_port - extract port number from string */
38
39
char *get_port(char *data)
40
{
41
	const char *escl=strchr(data,'[');
42
	const char *sepl=strchr(data,':');
43
	char *escr=strrchr(data,']');
44
	char *sepr=strrchr(data,':');
45
46
	/* extract from "[address]:port" or "[address]"*/
47
	if (escl && escr)
48
	{
49
		memmove(data, data + 1, strlen(data) - strlen(escr));
50
		data[strlen(data) - strlen(escr) - 1] = 0;
51
		*escr++ = 0;
52
		if (*escr == ':')
53
			escr++;
54
		return (*escr ? escr : NULL);
55
	}
56
	/* extract from "address:port" or "address" */
57
	if ((sepl == sepr) && sepr && sepl)
58
	{
59
		*sepr++ = 0;
60
		return sepr;
61
	}
62
63
	/* return empty string */
64
	return NULL;
65
}
(-)postfix-1.1.11-20020613-orig/src/util/get_port.h (+28 lines)
Line 0 Link Here
1
#ifndef _GET_PORT_H_INCLUDED_
2
#define _GET_PORT_H_INCLUDED_
3
4
/*++
5
/* NAME
6
/*	get_port 3h
7
/* SUMMARY
8
/*	trivial host and port extracter
9
/* SYNOPSIS
10
/*	#include <get_port.h>
11
/* DESCRIPTION
12
/* .nf
13
14
 /* External interface. */
15
16
extern char *get_port(char *);
17
18
19
/* LICENSE
20
/* .ad
21
/* .fi
22
/*	BSD Style (or BSD like) license.
23
/* AUTHOR(S)
24
/*	Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
25
/*	Wroclaw, POLAND
26
/*--*/
27
28
#endif
(-)postfix-1.1.11-20020613-orig/src/util/inet_addr_host.c (-2 / +46 lines)
Lines 38-44 Link Here
38
#include <sys_defs.h>
38
#include <sys_defs.h>
39
#include <netinet/in.h>
39
#include <netinet/in.h>
40
#include <arpa/inet.h>
40
#include <arpa/inet.h>
41
#include <sys/socket.h>
41
#include <netdb.h>
42
#include <netdb.h>
43
#include <stdlib.h>
44
#include <string.h>
42
45
43
#ifndef INADDR_NONE
46
#ifndef INADDR_NONE
44
#define INADDR_NONE 0xffffffff
47
#define INADDR_NONE 0xffffffff
Lines 48-62 Link Here
48
51
49
#include <inet_addr_list.h>
52
#include <inet_addr_list.h>
50
#include <inet_addr_host.h>
53
#include <inet_addr_host.h>
54
#ifdef TEST
55
#include <msg.h>
56
#endif
51
57
52
/* inet_addr_host - look up address list for host */
58
/* inet_addr_host - look up address list for host */
53
59
54
int     inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
60
int     inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
55
{
61
{
62
#ifdef INET6
63
    int s;
64
    struct addrinfo hints, *res0, *res;
65
#ifdef TEST	
66
	char buforhosta[1024];
67
#endif	
68
    int error;
69
#else
56
    struct hostent *hp;
70
    struct hostent *hp;
57
    struct in_addr addr;
71
    struct in_addr addr;
72
#endif
58
    int     initial_count = addr_list->used;
73
    int     initial_count = addr_list->used;
59
74
75
#ifdef INET6
76
    memset(&hints, 0, sizeof(hints));
77
    hints.ai_family = PF_UNSPEC;
78
    hints.ai_socktype = SOCK_DGRAM;
79
    error = getaddrinfo(hostname, NULL, &hints, &res0);
80
    if (error == 0) {
81
	for (res = res0; res; res = res->ai_next) {
82
	    if(res->ai_family != AF_INET && res->ai_family != AF_INET6)
83
		continue;
84
	    /* filter out address families that are not supported */
85
	    s = socket(res->ai_family, SOCK_DGRAM, 0);
86
	    if (s < 0)
87
		continue;
88
	    close(s);
89
90
	    inet_addr_list_append(addr_list, res->ai_addr);
91
	}
92
	freeaddrinfo(res0);
93
    }
94
#else
60
    if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
95
    if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
61
	inet_addr_list_append(addr_list, &addr);
96
	inet_addr_list_append(addr_list, &addr);
62
    } else {
97
    } else {
Lines 65-73 Link Here
65
		inet_addr_list_append(addr_list,
100
		inet_addr_list_append(addr_list,
66
				    (struct in_addr *) * hp->h_addr_list++);
101
				    (struct in_addr *) * hp->h_addr_list++);
67
    }
102
    }
103
#endif
104
68
    return (addr_list->used - initial_count);
105
    return (addr_list->used - initial_count);
69
}
106
}
70
107
108
71
#ifdef TEST
109
#ifdef TEST
72
110
73
#include <msg.h>
111
#include <msg.h>
Lines 78-83 Link Here
78
{
116
{
79
    INET_ADDR_LIST addr_list;
117
    INET_ADDR_LIST addr_list;
80
    int     i;
118
    int     i;
119
    struct sockaddr *sa;
120
    char hbuf[NI_MAXHOST];
81
121
82
    msg_vstream_init(argv[0], VSTREAM_ERR);
122
    msg_vstream_init(argv[0], VSTREAM_ERR);
83
123
Lines 89-96 Link Here
89
	if (inet_addr_host(&addr_list, *argv) == 0)
129
	if (inet_addr_host(&addr_list, *argv) == 0)
90
	    msg_fatal("not found: %s", *argv);
130
	    msg_fatal("not found: %s", *argv);
91
131
92
	for (i = 0; i < addr_list.used; i++)
132
	for (i = 0; i < addr_list.used; i++) {
93
	    vstream_printf("%s\n", inet_ntoa(addr_list.addrs[i]));
133
	    sa = (struct sockaddr *)&addr_list.addrs[i];
134
	    getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
135
		    NI_NUMERICHOST);
136
	    vstream_printf("%s\n", hbuf);
137
	}
94
	vstream_fflush(VSTREAM_OUT);
138
	vstream_fflush(VSTREAM_OUT);
95
    }
139
    }
96
    inet_addr_list_free(&addr_list);
140
    inet_addr_list_free(&addr_list);
(-)postfix-1.1.11-20020613-orig/src/util/inet_addr_list.c (+41 lines)
Lines 51-56 Link Here
51
#include <arpa/inet.h>
51
#include <arpa/inet.h>
52
#include <stdlib.h>
52
#include <stdlib.h>
53
53
54
#include <netdb.h>
55
56
#ifdef INET6
57
#include <string.h>
58
#include <sys/socket.h>
59
#endif
60
54
/* Utility library. */
61
/* Utility library. */
55
62
56
#include <msg.h>
63
#include <msg.h>
Lines 63-74 Link Here
63
{
70
{
64
    list->used = 0;
71
    list->used = 0;
65
    list->size = 2;
72
    list->size = 2;
73
#ifdef INET6
74
    list->addrs = (struct sockaddr_storage *)
75
#else
66
    list->addrs = (struct in_addr *)
76
    list->addrs = (struct in_addr *)
77
#endif
67
	mymalloc(sizeof(*list->addrs) * list->size);
78
	mymalloc(sizeof(*list->addrs) * list->size);
68
}
79
}
69
80
70
/* inet_addr_list_append - append address to internet address list */
81
/* inet_addr_list_append - append address to internet address list */
71
82
83
#ifdef INET6
84
void    inet_addr_list_append(INET_ADDR_LIST *list, 
85
                              struct sockaddr * addr)
86
{
87
    char   *myname = "inet_addr_list_append";
88
    char hbuf[NI_MAXHOST];
89
90
    if (msg_verbose > 1) {
91
	if (getnameinfo(addr, SA_LEN(addr), hbuf, sizeof(hbuf), NULL, 0,
92
	    NI_NUMERICHOST)) {
93
	    strncpy(hbuf, "??????", sizeof(hbuf));
94
	}
95
	msg_info("%s: %s", myname, hbuf);
96
    }
97
98
    if (list->used >= list->size)
99
	list->size *= 2;
100
    list->addrs = (struct sockaddr_storage *)
101
	myrealloc((char *) list->addrs,
102
		  sizeof(*list->addrs) * list->size);
103
    memcpy(&list->addrs[list->used++], addr, SA_LEN(addr));
104
}
105
#else
72
void    inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
106
void    inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
73
{
107
{
74
    char   *myname = "inet_addr_list_append";
108
    char   *myname = "inet_addr_list_append";
Lines 83-97 Link Here
83
		  sizeof(*list->addrs) * list->size);
117
		  sizeof(*list->addrs) * list->size);
84
    list->addrs[list->used++] = *addr;
118
    list->addrs[list->used++] = *addr;
85
}
119
}
120
#endif
86
121
87
/* inet_addr_list_comp - compare addresses */
122
/* inet_addr_list_comp - compare addresses */
88
123
89
static int inet_addr_list_comp(const void *a, const void *b)
124
static int inet_addr_list_comp(const void *a, const void *b)
90
{
125
{
126
#ifdef INET6
127
    if(((struct sockaddr*)a)->sa_family != ((struct sockaddr*)b)->sa_family)
128
	return ( ((struct sockaddr*)a)->sa_family - ((struct sockaddr*)b)->sa_family );
129
    return memcmp(a,b,SA_LEN((struct sockaddr*)a));
130
#else
91
    const struct in_addr *a_addr = (const struct in_addr *) a;
131
    const struct in_addr *a_addr = (const struct in_addr *) a;
92
    const struct in_addr *b_addr = (const struct in_addr *) b;
132
    const struct in_addr *b_addr = (const struct in_addr *) b;
93
133
94
    return (a_addr->s_addr - b_addr->s_addr);
134
    return (a_addr->s_addr - b_addr->s_addr);
135
#endif
95
}
136
}
96
137
97
/* inet_addr_list_uniq - weed out duplicates */
138
/* inet_addr_list_uniq - weed out duplicates */
(-)postfix-1.1.11-20020613-orig/src/util/inet_addr_list.h (+23 lines)
Lines 16-34 Link Here
16
  */
16
  */
17
#include <netinet/in.h>
17
#include <netinet/in.h>
18
18
19
#ifndef SA_LEN
20
# ifndef HAS_SA_LEN
21
#  define SA_LEN(x)	(((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
22
#  define SS_LEN(x)	(((x).ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
23
# else
24
#  define SA_LEN(x)       ((x)->sa_len)
25
#  define SS_LEN(x)       ((x).ss_len)
26
# endif
27
#else
28
# ifndef SS_LEN
29
#  define SS_LEN(x)	(((x).ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
30
# endif
31
#endif
32
	
19
 /*
33
 /*
20
  * External interface.
34
  * External interface.
21
  */
35
  */
22
typedef struct INET_ADDR_LIST {
36
typedef struct INET_ADDR_LIST {
23
    int     used;			/* nr of elements in use */
37
    int     used;			/* nr of elements in use */
24
    int     size;			/* actual list size */
38
    int     size;			/* actual list size */
39
#ifdef INET6
40
    struct sockaddr_storage *addrs;   /* payload */
41
#else
25
    struct in_addr *addrs;		/* payload */
42
    struct in_addr *addrs;		/* payload */
43
#endif
26
} INET_ADDR_LIST;
44
} INET_ADDR_LIST;
27
45
28
extern void inet_addr_list_init(INET_ADDR_LIST *);
46
extern void inet_addr_list_init(INET_ADDR_LIST *);
29
extern void inet_addr_list_free(INET_ADDR_LIST *);
47
extern void inet_addr_list_free(INET_ADDR_LIST *);
30
extern void inet_addr_list_uniq(INET_ADDR_LIST *);
48
extern void inet_addr_list_uniq(INET_ADDR_LIST *);
49
#ifdef INET6
50
struct sockaddr;
51
extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *);
52
#else
31
extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
53
extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
54
#endif
32
55
33
/* LICENSE
56
/* LICENSE
34
/* .ad
57
/* .ad
(-)postfix-1.1.11-20020613-orig/src/util/inet_addr_local.c (-5 / +164 lines)
Lines 47-52 Link Here
47
#endif
47
#endif
48
#include <errno.h>
48
#include <errno.h>
49
#include <string.h>
49
#include <string.h>
50
#if defined(INET6) && (defined (LINUX) || defined (LINUX2))
51
#include <netdb.h>
52
#include <stdio.h>
53
#endif
54
#ifdef HAVE_GETIFADDRS
55
#include <ifaddrs.h>
56
#endif
50
57
51
/* Utility library. */
58
/* Utility library. */
52
59
Lines 78-95 Link Here
78
85
79
int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
86
int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
80
{
87
{
88
#ifdef HAVE_GETIFADDRS
89
    char *myname = "inet_addr_local";
90
    struct ifaddrs *ifap, *ifa;
91
    int initial_count = addr_list->used;
92
    struct sockaddr *sa, *sam;
93
#ifdef INET6
94
#ifdef __KAME__
95
    struct sockaddr_in6 addr6;
96
#endif
97
#else
98
    void *addr,*addrm;
99
#endif
100
101
    if (getifaddrs(&ifap) < 0)
102
	msg_fatal("%s: getifaddrs: %m", myname);
103
104
    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
105
		if (! (ifa->ifa_flags & IFF_RUNNING) || ifa->ifa_addr==NULL) 
106
			continue;
107
	sa = ifa->ifa_addr;
108
	sam = ifa->ifa_netmask;
109
	switch (ifa->ifa_addr->sa_family) {
110
	case AF_INET:
111
#ifndef INET6
112
	    addr = (void *)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
113
	    addrm = (void *)&((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
114
#endif
115
	    break;
116
#ifdef INET6
117
	case AF_INET6:
118
#ifdef __KAME__
119
	    memcpy(&addr6, ifa->ifa_addr, ifa->ifa_addr->sa_len);
120
	    /* decode scoped address notation */
121
	    if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) ||
122
	         IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) &&
123
		addr6.sin6_scope_id == 0) {
124
		addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] |
125
		    (unsigned int)addr6.sin6_addr.s6_addr[2] << 8);
126
		addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
127
		sa = (struct sockaddr *)&addr6;
128
	    }
129
#endif
130
	    break;
131
#endif
132
	default:
133
	    continue;
134
	}
135
136
#ifdef INET6
137
	inet_addr_list_append(addr_list, sa);
138
	if (mask_list != NULL)
139
	    inet_addr_list_append(mask_list, sam);
140
#else
141
	inet_addr_list_append(addr_list, (struct in_addr *)addr);
142
	if (mask_list != NULL)
143
	    inet_addr_list_append(mask_list, (struct in_addr *)addrm);
144
#endif
145
    }
146
147
    freeifaddrs(ifap);
148
    return (addr_list->used - initial_count);
149
#else
81
    char   *myname = "inet_addr_local";
150
    char   *myname = "inet_addr_local";
82
    struct ifconf ifc;
151
    struct ifconf ifc;
83
    struct ifreq *ifr;
152
    struct ifreq *ifr;
84
    struct ifreq *the_end;
153
    struct ifreq *the_end;
85
    int     sock;
154
    int     sock;
86
    VSTRING *buf = vstring_alloc(1024);
155
    VSTRING *buf;
87
    int     initial_count = addr_list->used;
156
    int     initial_count = addr_list->used;
88
    struct in_addr addr;
157
    struct in_addr addr;
89
    struct ifreq *ifr_mask;
158
    struct ifreq *ifr_mask;
159
    int af = AF_INET;
160
#ifdef INET6
161
#if defined (LINUX) || defined (LINUX2)
162
#define _PATH_PROCNET_IFINET6   "/proc/net/if_inet6"
163
    FILE *f;
164
    char addr6p[8][5], addr6res[40], devname[20];
165
    int plen, scope, dad_status, if_idx, gaierror;
166
    struct addrinfo hints, *res, *res0;
167
#endif
168
    struct sockaddr_in6 addr6;
90
169
91
    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
170
other_socket_type:
171
#endif
172
    buf = vstring_alloc(1024);
173
174
    if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) {
175
#ifdef INET6
176
	if (af == AF_INET6)
177
	{
178
	    if (msg_verbose)
179
		    msg_warn("%s: socket: %m", myname);
180
	    goto end;
181
	}
182
	else
183
#endif
92
	msg_fatal("%s: socket: %m", myname);
184
	msg_fatal("%s: socket: %m", myname);
185
    }
93
186
94
    /*
187
    /*
95
     * Get the network interface list. XXX The socket API appears to have no
188
     * Get the network interface list. XXX The socket API appears to have no
Lines 126-135 Link Here
126
     */
219
     */
127
    the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
220
    the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
128
    for (ifr = ifc.ifc_req; ifr < the_end;) {
221
    for (ifr = ifc.ifc_req; ifr < the_end;) {
129
	if (ifr->ifr_addr.sa_family == AF_INET) {	/* IP interface */
222
	if ((ifr->ifr_addr.sa_family == AF_INET) &&
223
			(ifr->ifr_addr.sa_family == af)) { /* IP interface */
130
	    addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
224
	    addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
131
	    if (addr.s_addr != INADDR_ANY) {	/* has IP address */
225
	    if (addr.s_addr != INADDR_ANY) {	/* has IP address */
226
#ifdef INET6
227
		inet_addr_list_append(addr_list, &ifr->ifr_addr);
228
#else
132
		inet_addr_list_append(addr_list, &addr);
229
		inet_addr_list_append(addr_list, &addr);
230
#endif
133
		if (mask_list) {
231
		if (mask_list) {
134
		    ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
232
		    ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
135
		    memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
233
		    memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
Lines 141-151 Link Here
141
		}
239
		}
142
	    }
240
	    }
143
	}
241
	}
242
#ifdef INET6
243
	else if ((ifr->ifr_addr.sa_family == AF_INET6) &&
244
			(ifr->ifr_addr.sa_family == af)) {  /* IPv6 interface */
245
	    addr6 = *((struct sockaddr_in6 *) & ifr->ifr_addr);
246
#ifdef __KAME__
247
	    /* decode scoped address notation */
248
	    if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) ||
249
	         IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) &&
250
		addr6.sin6_scope_id == 0) {
251
		addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] |
252
		    (unsigned int)addr6.sin6_addr.s6_addr[2] << 8);
253
		addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
254
	    }
255
#endif
256
	    if (!(IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr)))
257
	        inet_addr_list_append(addr_list, (struct sockaddr *)&addr6);
258
	}
259
#endif
144
	ifr = NEXT_INTERFACE(ifr);
260
	ifr = NEXT_INTERFACE(ifr);
145
    }
261
    }
146
    vstring_free(buf);
262
    vstring_free(buf);
147
    (void) close(sock);
263
    (void) close(sock);
264
#ifdef INET6
265
end:
266
    if (af != AF_INET6) {
267
	    af = AF_INET6;
268
	    goto other_socket_type;
269
    }
270
#if defined (LINUX) || defined (LINUX2)
271
    if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
272
         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
273
	       addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
274
	       addr6p[5], addr6p[6], addr6p[7],
275
	       &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
276
		 sprintf(addr6res, "%s:%s:%s:%s:%s:%s:%s:%s",
277
				 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
278
				 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
279
		 addr6res[sizeof(addr6res) - 1] = 0;
280
		 memset(&hints, 0, sizeof(hints));
281
		 hints.ai_flags = AI_NUMERICHOST;
282
		 hints.ai_family = AF_UNSPEC;
283
		 hints.ai_socktype = SOCK_DGRAM;
284
		 gaierror = getaddrinfo(addr6res, NULL, &hints, &res0);
285
		 if (!gaierror) {
286
			 for (res = res0; res; res = res->ai_next) {
287
			       inet_addr_list_append(addr_list, res->ai_addr);
288
			 }
289
			 freeaddrinfo(res0);
290
		 }
291
	 }
292
    }
293
#endif /* linux */
294
#endif
148
    return (addr_list->used - initial_count);
295
    return (addr_list->used - initial_count);
296
#endif
149
}
297
}
150
298
151
#ifdef TEST
299
#ifdef TEST
Lines 158-163 Link Here
158
    INET_ADDR_LIST addr_list;
306
    INET_ADDR_LIST addr_list;
159
    INET_ADDR_LIST mask_list;
307
    INET_ADDR_LIST mask_list;
160
    int     i;
308
    int     i;
309
    char abuf[NI_MAXHOST], mbuf[NI_MAXHOST];
310
    struct sockaddr *sa;
161
311
162
    msg_vstream_init(argv[0], VSTREAM_ERR);
312
    msg_vstream_init(argv[0], VSTREAM_ERR);
163
313
Lines 172-179 Link Here
172
	msg_warn("found only one active network interface");
322
	msg_warn("found only one active network interface");
173
323
174
    for (i = 0; i < addr_list.used; i++) {
324
    for (i = 0; i < addr_list.used; i++) {
175
	vstream_printf("%s/", inet_ntoa(addr_list.addrs[i]));
325
	sa = (struct sockaddr *)&addr_list.addrs[i];
176
	vstream_printf("%s\n", inet_ntoa(mask_list.addrs[i]));
326
	if (getnameinfo(sa, SA_LEN(sa), abuf, sizeof(abuf), NULL, 0,
327
		NI_NUMERICHOST)) {
328
	    strncpy(abuf, "???", sizeof(abuf));
329
	}
330
	sa = (struct sockaddr *)&mask_list.addrs[i];
331
	if (getnameinfo(sa, SA_LEN(sa), mbuf, sizeof(mbuf), NULL, 0,
332
		NI_NUMERICHOST)) {
333
	    strncpy(mbuf, "???", sizeof(mbuf));
334
	}
335
	vstream_printf("%s/%s\n", abuf, mbuf);
177
    }
336
    }
178
    vstream_fflush(VSTREAM_OUT);
337
    vstream_fflush(VSTREAM_OUT);
179
    inet_addr_list_free(&addr_list);
338
    inet_addr_list_free(&addr_list);
(-)postfix-1.1.11-20020613-orig/src/util/inet_connect.c (+53 lines)
Lines 55-60 Link Here
55
#include <string.h>
55
#include <string.h>
56
#include <unistd.h>
56
#include <unistd.h>
57
#include <errno.h>
57
#include <errno.h>
58
#ifdef INET6
59
#include <netdb.h>
60
#endif
58
61
59
/* Utility library. */
62
/* Utility library. */
60
63
Lines 73-79 Link Here
73
    char   *buf;
76
    char   *buf;
74
    char   *host;
77
    char   *host;
75
    char   *port;
78
    char   *port;
79
#ifdef INET6
80
    struct addrinfo hints, *res, *res0;
81
    int    error;
82
#else
76
    struct sockaddr_in sin;
83
    struct sockaddr_in sin;
84
#endif
77
    int     sock;
85
    int     sock;
78
86
79
    /*
87
    /*
Lines 81-94 Link Here
81
     * the local host.
89
     * the local host.
82
     */
90
     */
83
    buf = inet_parse(addr, &host, &port);
91
    buf = inet_parse(addr, &host, &port);
92
#ifdef INET6
93
    if (*host == 0)
94
	host = NULL;
95
    memset(&hints, 0, sizeof(hints));
96
    hints.ai_family = PF_UNSPEC;
97
    hints.ai_socktype = SOCK_STREAM;
98
    hints.ai_flags = AI_NUMERICHOST;	/* find_inet_addr is numeric only */
99
    if (getaddrinfo(host, port, &hints, &res0))
100
	msg_fatal("host not found: %s", host);
101
#else
84
    if (*host == 0)
102
    if (*host == 0)
85
	host = "localhost";
103
	host = "localhost";
86
    memset((char *) &sin, 0, sizeof(sin));
104
    memset((char *) &sin, 0, sizeof(sin));
87
    sin.sin_family = AF_INET;
105
    sin.sin_family = AF_INET;
88
    sin.sin_addr.s_addr = find_inet_addr(host);
106
    sin.sin_addr.s_addr = find_inet_addr(host);
89
    sin.sin_port = find_inet_port(port, "tcp");
107
    sin.sin_port = find_inet_port(port, "tcp");
108
#endif
90
    myfree(buf);
109
    myfree(buf);
91
110
111
#ifdef INET6
112
    sock = -1;
113
    for (res = res0; res; res = res->ai_next) {
114
	if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
115
	    continue;
116
117
	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
118
	if (sock < 0)
119
	    continue;
120
	if (timeout > 0) {
121
	    non_blocking(sock, NON_BLOCKING);
122
	    if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) {
123
		close(sock);
124
		sock = -1;
125
		continue;
126
	    }
127
	    if (block_mode != NON_BLOCKING)
128
		non_blocking(sock, block_mode);
129
	    break;
130
	} else {
131
	    non_blocking(sock, block_mode);
132
	    if (connect(sock, res->ai_addr, res->ai_addrlen) < 0
133
		&& errno != EINPROGRESS) {
134
		close(sock);
135
		sock = -1;
136
		continue;
137
	    }
138
	    break;
139
	}
140
    }
141
    freeaddrinfo(res0);
142
    return sock;
143
#else
92
    /*
144
    /*
93
     * Create a client socket.
145
     * Create a client socket.
94
     */
146
     */
Lines 121-124 Link Here
121
	}
173
	}
122
	return (sock);
174
	return (sock);
123
    }
175
    }
176
#endif
124
}
177
}
(-)postfix-1.1.11-20020613-orig/src/util/inet_listen.c (-14 / +101 lines)
Lines 6-12 Link Here
6
/* SYNOPSIS
6
/* SYNOPSIS
7
/*	#include <listen.h>
7
/*	#include <listen.h>
8
/*
8
/*
9
/*	int	inet_listen(addr, backlog, block_mode)
9
/*	int	inet_listen(addr, backlog, block_mode, addinuse_fatal)
10
/*	const char *addr;
10
/*	const char *addr;
11
/*	int	backlog;
11
/*	int	backlog;
12
/*	int	block_mode;
12
/*	int	block_mode;
Lines 51-61 Link Here
51
#include <sys_defs.h>
51
#include <sys_defs.h>
52
#include <sys/socket.h>
52
#include <sys/socket.h>
53
#include <netinet/in.h>
53
#include <netinet/in.h>
54
#ifdef INET6
55
#if (! __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 )
56
#include <netinet6/in6.h>
57
#endif
58
#endif
54
#include <arpa/inet.h>
59
#include <arpa/inet.h>
55
#include <netdb.h>
60
#include <netdb.h>
56
#ifndef MAXHOSTNAMELEN
61
#ifndef MAXHOSTNAMELEN
57
#include <sys/param.h>
62
#include <sys/param.h>
58
#endif
63
#endif
64
#include <errno.h>
59
#include <string.h>
65
#include <string.h>
60
#include <unistd.h>
66
#include <unistd.h>
61
67
Lines 77-111 Link Here
77
83
78
/* inet_listen - create inet-domain listener */
84
/* inet_listen - create inet-domain listener */
79
85
80
int     inet_listen(const char *addr, int backlog, int block_mode)
86
int     inet_listen(const char *addr, int backlog, int block_mode, int addrinuse_fatal)
81
{
87
{
88
#ifdef INET6
89
    struct addrinfo *res, *res0, hints;
90
    int error;
91
#else
92
    struct ai {
93
	int ai_family;
94
	int ai_socktype;
95
	int ai_protocol;
96
	struct sockaddr *ai_addr;
97
	SOCKADDR_SIZE ai_addrlen;
98
	struct ai *ai_next;
99
    } *res, *res0, resbody;
82
    struct sockaddr_in sin;
100
    struct sockaddr_in sin;
101
#endif
83
    int     sock;
102
    int     sock;
84
    int     t = 1;
103
    int     t = 1;
104
    int     addrinuse = 0;
85
    char   *buf;
105
    char   *buf;
86
    char   *host;
106
    char   *host;
87
    char   *port;
107
    char   *port;
108
#ifdef INET6
109
    char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
110
#else
111
    char hbuf[sizeof("255.255.255.255") + 1];
112
    char pbuf[sizeof("255.255.255.255") + 1];
113
#endif
114
    char *cause = "unknown";
88
115
89
    /*
116
    /*
90
     * Translate address information to internal form.
117
     * Translate address information to internal form.
91
     */
118
     */
92
    buf = inet_parse(addr, &host, &port);
119
    buf = inet_parse(addr, &host, &port);
93
    memset((char *) &sin, 0, sizeof(sin));
120
#ifdef INET6
121
    memset(&hints, 0, sizeof(hints));
122
    hints.ai_flags = AI_PASSIVE;
123
    hints.ai_family = AF_UNSPEC;
124
    hints.ai_socktype = SOCK_STREAM;
125
    error = getaddrinfo(*host ? host : NULL, *port ? port : "0", &hints, &res0);
126
    if (error) {
127
	msg_fatal("getaddrinfo: %s", gai_strerror(error));
128
    }
129
    myfree(buf);
130
#else
131
    memset(&sin, 0, sizeof(sin));
94
    sin.sin_family = AF_INET;
132
    sin.sin_family = AF_INET;
133
#ifdef HAS_SA_LEN
134
    sin.sin_len = sizeof(sin);
135
#endif
95
    sin.sin_port = find_inet_port(port, "tcp");
136
    sin.sin_port = find_inet_port(port, "tcp");
96
    sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY);
137
    sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY);
97
    myfree(buf);
98
138
99
    /*
139
    memset(&resbody, 0, sizeof(resbody)); 
100
     * Create a listener socket.
140
    resbody.ai_socktype = SOCK_STREAM;
101
     */
141
    resbody.ai_family = AF_INET;
102
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
142
    resbody.ai_addr = (struct sockaddr *)&sin;
103
	msg_fatal("socket: %m");
143
    resbody.ai_addrlen = sizeof(sin);
104
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0)
144
105
	msg_fatal("setsockopt: %m");
145
    res0 = &resbody;
106
    if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
146
#endif
107
	msg_fatal("bind %s port %d: %m", sin.sin_addr.s_addr == INADDR_ANY ?
147
108
	       "INADDR_ANY" : inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
148
    sock = -1;
149
    for (res = res0; res; res = res->ai_next) {
150
	if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
151
	    continue;
152
153
	/*
154
	 * Create a listener socket.
155
	 */
156
	if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0) {
157
	    cause = "socket";
158
	    continue;
159
	}
160
#ifdef IPV6_V6ONLY
161
	if (res->ai_family == AF_INET6 &&
162
	    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &t, sizeof(t)) < 0) {
163
		/* if kernel/libc don't support this simple ignore it
164
	    cause = "setsockopt(IPV6_V6ONLY)";
165
	    close(sock);
166
	    sock = -1;
167
	    continue;
168
		*/
169
		;
170
	}
171
#endif
172
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) {
173
	    cause = "setsockopt(SO_REUSEADDR)";
174
	    close(sock);
175
	    sock = -1;
176
	    continue;
177
	}
178
179
	if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
180
	    cause = "bind";
181
	    if (errno == EADDRINUSE)
182
		addrinuse = 1;
183
	    close(sock);
184
	    sock = -1;
185
	    continue;
186
	}
187
	break;
188
    }
189
    if (sock < 0 && (addrinuse_fatal || !addrinuse))
190
	msg_fatal("%s: %m", cause);
191
#ifdef INET6
192
    freeaddrinfo(res0);
193
#endif
194
    if (sock < 0)
195
	return -1;
109
    non_blocking(sock, block_mode);
196
    non_blocking(sock, block_mode);
110
    if (listen(sock, backlog) < 0)
197
    if (listen(sock, backlog) < 0)
111
	msg_fatal("listen: %m");
198
	msg_fatal("listen: %m");
(-)postfix-1.1.11-20020613-orig/src/util/listen.h (-1 / +1 lines)
Lines 20-26 Link Here
20
  * Listener external interface.
20
  * Listener external interface.
21
  */
21
  */
22
extern int unix_listen(const char *, int, int);
22
extern int unix_listen(const char *, int, int);
23
extern int inet_listen(const char *, int, int);
23
extern int inet_listen(const char *, int, int, int);
24
extern int fifo_listen(const char *, int, int);
24
extern int fifo_listen(const char *, int, int);
25
extern int stream_listen(const char *, int, int);
25
extern int stream_listen(const char *, int, int);
26
26
(-)postfix-1.1.11-20020613-orig/src/util/match_list.c (-1 / +1 lines)
Lines 118-124 Link Here
118
		    list = match_list_parse(list, vstring_str(buf));
118
		    list = match_list_parse(list, vstring_str(buf));
119
	    if (vstream_fclose(fp))
119
	    if (vstream_fclose(fp))
120
		msg_fatal("%s: read file %s: %m", myname, pattern);
120
		msg_fatal("%s: read file %s: %m", myname, pattern);
121
	} else if (strchr(pattern, ':') != 0) {	/* type:table */
121
	} else if ((strchr(pattern, ']') == 0) && (strchr(pattern, ':') != 0)) {	/* type:table */
122
	    for (cp = pattern; *cp == '!'; cp++)
122
	    for (cp = pattern; *cp == '!'; cp++)
123
		 /* void */ ;
123
		 /* void */ ;
124
	    if (dict_handle(pattern) == 0)
124
	    if (dict_handle(pattern) == 0)
(-)postfix-1.1.11-20020613-orig/src/util/match_ops.c (-1 / +352 lines)
Lines 81-86 Link Here
81
#include <match_ops.h>
81
#include <match_ops.h>
82
#include <stringops.h>
82
#include <stringops.h>
83
83
84
#ifdef INET6
85
/*
86
 *		$Id: match_ops.c,v 1.2 2000/05/22 12:01:17 misiek Exp $
87
 *
88
 *		This program is free software; you can redistribute it and/or
89
 *		modify it under the terms of the GNU General Public License
90
 *		as published by the Free Software Foundation; either version
91
 *		2 of the License, or (at your option) any later version.
92
 *
93
 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
94
 * 
95
 * Modifications:
96
 *		Artur Frysiak <wiget@pld.org.pl>
97
 *		Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
98
 */
99
100
#include <stdio.h>
101
#include <stdlib.h>
102
#include <unistd.h>
103
#include <syslog.h>
104
#include <fcntl.h>
105
#include <sys/socket.h>
106
#include <netinet/in.h>
107
#include <string.h>
108
#include <netdb.h>
109
#include <arpa/inet.h>
110
#include <resolv.h>
111
112
#ifndef	AF_DECnet
113
#define	AF_DECnet	12
114
#endif
115
116
#ifndef	PF_PACKET
117
#define	PF_PACKET	17
118
#endif
119
120
typedef struct
121
{
122
	unsigned char family;
123
	unsigned char bytelen;
124
	signed short  bitlen;
125
	unsigned int data[4];
126
} inet_prefix;
127
128
/* prototypes */
129
int masked_match(char *, char *, char *);
130
int get_integer(int *, char *, int);
131
int get_addr_1(inet_prefix *, char *, int);
132
int get_prefix_1(inet_prefix *, char *, int);
133
int get_addr(inet_prefix *, char *, int);
134
int get_prefix(inet_prefix *, char *, int);
135
unsigned int get_addr32(char *);
136
int matches(char *, char *);
137
int inet_addr_match(inet_prefix *, inet_prefix *, int);
138
int mask_match(char *, char *, char *);
139
	
140
int get_integer(int *val, char *arg, int base)
141
{
142
	long res;
143
	char *ptr;
144
145
	if (!arg || !*arg)
146
		return -1;
147
	res = strtol(arg, &ptr, base);
148
	if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
149
		return -1;
150
	*val = res;
151
	return 0;
152
}
153
154
int get_addr_1(inet_prefix *addr, char *name, int family)
155
{
156
	char *cp;
157
	unsigned char *ap = (unsigned char*)addr->data;
158
	int i;
159
160
	memset(addr, 0, sizeof(*addr));
161
162
	if (strcmp(name, "default") == 0 || strcmp(name, "any") == 0) {
163
		if (family == AF_DECnet)
164
			return -1;
165
		addr->family = family;
166
		addr->bytelen = (family == AF_INET6 ? 16 : 4);
167
		addr->bitlen = -1;
168
		return 0;
169
	}
170
171
	if (strchr(name, ':')) {
172
		addr->family = AF_INET6;
173
		if (family != AF_UNSPEC && family != AF_INET6)
174
			return -1;
175
		if (inet_pton(AF_INET6, name, addr->data) <= 0)
176
			return -1;
177
		addr->bytelen = 16;
178
		addr->bitlen = -1;
179
		return 0;
180
	}
181
	addr->family = AF_INET;
182
	if (family != AF_UNSPEC && family != AF_INET)
183
		return -1;
184
	addr->bytelen = 4;
185
	addr->bitlen = -1;
186
	for (cp = name, i = 0; *cp; cp++) {
187
		if (*cp <= '9' && *cp >= '0') {
188
			ap[i] = 10*ap[i] + (*cp-'0');
189
			continue;
190
		}
191
		if (*cp == '.' && ++i <= 3)
192
			continue;
193
		return -1;
194
	}
195
	return 0;
196
}
197
198
int get_prefix_1(inet_prefix *dst, char *arg, int family)
199
{
200
	int err;
201
	unsigned plen;
202
	char *slash;
203
204
	memset(dst, 0, sizeof(*dst));
205
206
	if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
207
		if (family == AF_DECnet)
208
			return -1;
209
		dst->family = family;
210
		dst->bytelen = 0;
211
		dst->bitlen = 0;
212
		return 0;
213
	}
214
215
	slash = strchr(arg, '/');
216
	if (slash)
217
		*slash = 0;
218
	err = get_addr_1(dst, arg, family);
219
	if (err == 0) {
220
		switch(dst->family) {
221
			case AF_INET6:
222
				dst->bitlen = 128;
223
				break;
224
			case AF_DECnet:
225
				dst->bitlen = 16;
226
				break;
227
			default:
228
			case AF_INET:
229
				dst->bitlen = 32;
230
		}
231
		if (slash) {
232
			if (get_integer(&plen, slash+1, 0) || plen > dst->bitlen) {
233
				err = -1;
234
				goto done;
235
			}
236
			dst->bitlen = plen;
237
		}
238
	}
239
done:
240
	if (slash)
241
		*slash = '/';
242
	return err;
243
}
244
245
int get_addr(inet_prefix *dst, char *arg, int family)
246
{
247
#ifdef AF_PACKET
248
	if (family == AF_PACKET)
249
		return -1;
250
#endif
251
	if (get_addr_1(dst, arg, family))
252
		return -1;
253
	return 0;
254
}
255
256
int get_prefix(inet_prefix *dst, char *arg, int family)
257
{
258
#ifdef AF_PACKET
259
	if (family == AF_PACKET)
260
		return -1;
261
#endif
262
	if (get_prefix_1(dst, arg, family))
263
		return -1;
264
	return 0;
265
}
266
267
unsigned int get_addr32(char *name)
268
{
269
	inet_prefix addr;
270
	if (get_addr_1(&addr, name, AF_INET))
271
		return -1;
272
	return addr.data[0];
273
}
274
275
int matches(char *cmd, char *pattern)
276
{
277
	int len = strlen(cmd);
278
	if (len > strlen(pattern))
279
		return -1;
280
	return memcmp(pattern, cmd, len);
281
}
282
283
int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
284
{
285
	unsigned int *a1 = a->data;
286
	unsigned int *a2 = b->data;
287
	int words = bits >> 0x05;
288
289
	bits &= 0x1f;
290
291
	if (words)
292
		if (memcmp(a1, a2, words << 2))
293
			return -1;
294
295
	if (bits) {
296
		unsigned int w1, w2;
297
		unsigned int mask;
298
299
		w1 = a1[words];
300
		w2 = a2[words];
301
302
		mask = htonl((0xffffffff) << (0x20 - bits));
303
304
		if ((w1 ^ w2) & mask)
305
			return 1;
306
	}
307
308
	return 0;
309
}
310
311
/* zero if matches */
312
int mask_match(char *network, char *cprefix, char *address)
313
{
314
 	inet_prefix *inetwork;
315
	inet_prefix *iaddress;
316
	int ret, prefix;
317
318
	if (!(network && address && cprefix))
319
		return -1;
320
	prefix = strtol(cprefix, (char **)NULL, 10);
321
	if ((prefix < 0) || (prefix > 128))
322
		return -1;
323
	if ((strlen(network) == 0) || (strlen(address) == 0))
324
		return -1;
325
326
	inetwork = malloc(sizeof(inet_prefix));
327
	iaddress = malloc(sizeof(inet_prefix));
328
329
	if ((get_addr(iaddress, address, AF_UNSPEC) >= 0)
330
			&& (get_addr(inetwork, network, AF_UNSPEC) >= 0))
331
		ret = inet_addr_match(inetwork, iaddress, prefix);
332
	else
333
		ret = -1;
334
	free(inetwork);
335
	free(iaddress);
336
337
	/* 1 if matches */
338
	/* return (!ret); */
339
	/* 0 if matches */
340
	return ret;
341
}
342
343
/*
344
 * masked_match() - universal for IPv4 and IPv6  - 1 if matches
345
 */
346
int masked_match(net_tok, mask_tok, string)
347
char	*net_tok;
348
char	*mask_tok;
349
char	*string;
350
{
351
#ifdef INET6
352
	struct in6_addr in6[2];
353
	char v4addr[2][INET_ADDRSTRLEN];
354
	char newmask[6];
355
	int plen;
356
#endif
357
358
	/* Check for NULL */
359
	if (!(net_tok && mask_tok && string))
360
		return 0; /* doesn't match!!! */
361
362
	/* If IPv6 mapped convert to native-IPv4 */
363
#ifdef INET6
364
	if (inet_pton(AF_INET6, net_tok, &in6[0]) == 1 &&
365
	    inet_pton(AF_INET6, string, &in6[1]) == 1 &&
366
	    IN6_IS_ADDR_V4MAPPED(&in6[0]) && IN6_IS_ADDR_V4MAPPED(&in6[1])) {
367
		plen = atoi(mask_tok);
368
		if (32 < plen && plen < 129) {
369
			sprintf(newmask, "%d", plen - 96);
370
			mask_tok = newmask;
371
		}
372
373
		(void)inet_ntop(AF_INET, &in6[0].s6_addr[12], v4addr[0],
374
		    sizeof(v4addr[0]));
375
		net_tok = v4addr[0];
376
		(void)inet_ntop(AF_INET, &in6[1].s6_addr[12], v4addr[1],
377
		    sizeof(v4addr[1]));
378
		string = v4addr[1];
379
	}
380
#endif
381
	return (!mask_match(net_tok, mask_tok, string));
382
}
383
#endif
384
84
/* match_string - match a string literal */
385
/* match_string - match a string literal */
85
386
86
int     match_string(int unused_flags, const char *string, const char *pattern)
387
int     match_string(int unused_flags, const char *string, const char *pattern)
Lines 177-182 Link Here
177
    return (0);
478
    return (0);
178
}
479
}
179
480
481
#ifndef INET6
180
/* match_parse_mask - parse net/mask pattern */
482
/* match_parse_mask - parse net/mask pattern */
181
483
182
static int match_parse_mask(const char *pattern, unsigned long *net_bits,
484
static int match_parse_mask(const char *pattern, unsigned long *net_bits,
Lines 198-224 Link Here
198
    return (mask != 0);
500
    return (mask != 0);
199
}
501
}
200
502
503
#endif
504
201
/* match_hostaddr - match host by address */
505
/* match_hostaddr - match host by address */
202
506
203
int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
507
int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
204
{
508
{
205
    char   *myname = "match_hostaddr";
509
    char   *myname = "match_hostaddr";
510
#ifdef INET6
511
    char *network, *mask, *escl, *escr, *patternx;
512
    struct in6_addr in6;
513
    char v4addr[INET_ADDRSTRLEN];
514
#else
206
    int     mask_shift;
515
    int     mask_shift;
207
    unsigned long mask_bits;
516
    unsigned long mask_bits;
208
    unsigned long net_bits;
517
    unsigned long net_bits;
209
    unsigned long addr_bits;
518
    unsigned long addr_bits;
519
#endif
210
520
211
    if (msg_verbose)
521
    if (msg_verbose)
212
	msg_info("%s: %s ~? %s", myname, addr, pattern);
522
	msg_info("%s: %s ~? %s", myname, addr, pattern);
213
523
524
#ifdef INET6
525
    if (addr[strspn(addr, "01234567890./:abcdef")] != 0)
526
#else
214
    if (addr[strspn(addr, "01234567890./:")] != 0)
527
    if (addr[strspn(addr, "01234567890./:")] != 0)
528
#endif
215
	return (0);
529
	return (0);
216
530
531
#ifdef INET6
532
    patternx = mystrdup(pattern);
533
    escl = strchr(patternx,'[');
534
    escr = strrchr(patternx,']');
535
    if (escl && escr) {
536
      *escr = 0;
537
      sprintf(patternx, "%s%s", escl + 1, escr + 1);
538
      pattern = patternx;
539
    }
540
#endif
541
217
    /*
542
    /*
218
     * Try dictionary lookup. This can be case insensitive. XXX Probably
543
     * Try dictionary lookup. This can be case insensitive. XXX Probably
219
     * should also try again after stripping least significant octets.
544
     * should also try again after stripping least significant octets.
220
     */
545
     */
221
    if (strchr(pattern, ':') != 0) {
546
#ifdef INET6
547
    if (!(escl && escr) && strchr(pattern, ':') != 0)
548
#else
549
    if (strchr(pattern, ':') != 0)
550
#endif
551
    {
222
	if (dict_lookup(pattern, addr) != 0)
552
	if (dict_lookup(pattern, addr) != 0)
223
	    return (1);
553
	    return (1);
224
	if (dict_errno != 0)
554
	if (dict_errno != 0)
Lines 229-234 Link Here
229
    /*
559
    /*
230
     * Try an exact match with the host address.
560
     * Try an exact match with the host address.
231
     */
561
     */
562
#ifdef INET6
563
    if (inet_pton(AF_INET6, addr, &in6) == 1 && IN6_IS_ADDR_V4MAPPED(&in6)) {
564
	(void)inet_ntop(AF_INET, &in6.s6_addr[12], v4addr, sizeof(v4addr));
565
	addr = v4addr;
566
    }
567
#endif
232
    if (strcasecmp(addr, pattern) == 0) {
568
    if (strcasecmp(addr, pattern) == 0) {
233
	return (1);
569
	return (1);
234
    }
570
    }
Lines 237-242 Link Here
237
     * In a net/mask pattern, the mask is specified as the number of bits of
573
     * In a net/mask pattern, the mask is specified as the number of bits of
238
     * the network part.
574
     * the network part.
239
     */
575
     */
576
#ifdef INET6
577
    network = mystrdup(patternx);
578
    mask = split_at(network, '/');
579
580
    if (masked_match(network, mask, (char *)addr)) {
581
	myfree(network);
582
	myfree(patternx);
583
	return (1);
584
    } else {
585
	myfree(network);
586
	myfree(patternx);
587
    }
588
#else
589
	    
240
    if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
590
    if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
241
	addr_bits = inet_addr(addr);
591
	addr_bits = inet_addr(addr);
242
	if (addr_bits == INADDR_NONE)
592
	if (addr_bits == INADDR_NONE)
Lines 244-248 Link Here
244
	mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
594
	mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
245
	return ((addr_bits & mask_bits) == (net_bits & mask_bits));
595
	return ((addr_bits & mask_bits) == (net_bits & mask_bits));
246
    }
596
    }
597
#endif
247
    return (0);
598
    return (0);
248
}
599
}
(-)postfix-1.1.11-20020613-orig/src/util/sdbm.c (+971 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*      sdbm 3h
4
/* SUMMARY
5
/*      SDBM Simple DBM: ndbm work-alike hashed database library
6
/* SYNOPSIS
7
/*      include "sdbm.h"
8
/* DESCRIPTION
9
/*	This file includes the public domain SDBM (ndbm work-alike hashed
10
/*	database library), based on Per-Aake Larson's Dynamic Hashing
11
/*	algorithms. BIT 18 (1978).
12
/*	author: oz@nexus.yorku.ca
13
/*	status: public domain
14
/*	The file has been patched following the advice of Uwe Ohse
15
/*	<uwe@ohse.de>:
16
/*	--------------------------------------------------------------
17
/*	this patch fixes a problem with sdbms .dir file, which arrises when
18
/*	a second .dir block is needed for the first time. read() returns 0
19
/*	in that case, and the library forgot to initialize that new block.
20
/*
21
/*	A related problem is that the calculation of db->maxbno is wrong.
22
/*	It just appends 4096*BYTESIZ bits, which is not enough except for
23
/*	small databases (.dir basically doubles everytime it's too small).
24
/*	--------------------------------------------------------------
25
/*	According to Uwe Ohse, the patch has also been submitted to the
26
/*	author of SDBM. (The 4096*BYTESIZ bits comment may apply with a
27
/*	different size for Postfix/TLS, as the patch was sent against the
28
/*	original SDBM distributiona and for Postfix/TLS I have changed the
29
/*	default sizes.
30
/* .nf
31
/*--*/
32
33
/*
34
 * sdbm - ndbm work-alike hashed database library
35
 * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
36
 * author: oz@nexus.yorku.ca
37
 * status: public domain.
38
 *
39
 * core routines
40
 */
41
42
#include <stdio.h>
43
#include <stdlib.h>
44
#ifdef WIN32
45
#include <io.h>
46
#include <errno.h>
47
#else
48
#include <unistd.h>
49
#endif
50
#include <sys/types.h>
51
#include <sys/stat.h>
52
#include <fcntl.h>
53
#include <errno.h>
54
#include <string.h>
55
#ifdef __STDC__
56
#include <stddef.h>
57
#endif
58
59
#include <sdbm.h>
60
61
/*
62
 * useful macros
63
 */
64
#define bad(x)          ((x).dptr == NULL || (x).dsize <= 0)
65
#define exhash(item)    sdbm_hash((item).dptr, (item).dsize)
66
#define ioerr(db)       ((db)->flags |= DBM_IOERR)
67
68
#define OFF_PAG(off)    (long) (off) * PBLKSIZ
69
#define OFF_DIR(off)    (long) (off) * DBLKSIZ
70
71
static long masks[] =
72
{
73
    000000000000, 000000000001, 000000000003, 000000000007,
74
    000000000017, 000000000037, 000000000077, 000000000177,
75
    000000000377, 000000000777, 000000001777, 000000003777,
76
    000000007777, 000000017777, 000000037777, 000000077777,
77
    000000177777, 000000377777, 000000777777, 000001777777,
78
    000003777777, 000007777777, 000017777777, 000037777777,
79
    000077777777, 000177777777, 000377777777, 000777777777,
80
    001777777777, 003777777777, 007777777777, 017777777777
81
};
82
83
datum   nullitem =
84
{NULL, 0};
85
86
typedef struct
87
{
88
    int     dirf;			/* directory file descriptor */
89
    int     pagf;			/* page file descriptor */
90
    int     flags;			/* status/error flags, see below */
91
    long    maxbno;			/* size of dirfile in bits */
92
    long    curbit;			/* current bit number */
93
    long    hmask;			/* current hash mask */
94
    long    blkptr;			/* current block for nextkey */
95
    int     keyptr;			/* current key for nextkey */
96
    long    blkno;			/* current page to read/write */
97
    long    pagbno;			/* current page in pagbuf */
98
    char   *pagbuf;			/* page file block buffer */
99
    long    dirbno;			/* current block in dirbuf */
100
    char   *dirbuf;			/* directory file block buffer */
101
}       DBM;
102
103
104
/* ************************* */
105
106
/*
107
 * sdbm - ndbm work-alike hashed database library
108
 * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
109
 * author: oz@nexus.yorku.ca
110
 * status: public domain. keep it that way.
111
 *
112
 * hashing routine
113
 */
114
115
/*
116
 * polynomial conversion ignoring overflows
117
 * [this seems to work remarkably well, in fact better
118
 * then the ndbm hash function. Replace at your own risk]
119
 * use: 65599   nice.
120
 *      65587   even better.
121
 */
122
static long sdbm_hash (char *str, int len)
123
{
124
    unsigned long n = 0;
125
126
#ifdef DUFF
127
#define HASHC   n = *str++ + 65599 * n
128
    if (len > 0)
129
      {
130
	  int     loop = (len + 8 - 1) >> 3;
131
132
	  switch (len & (8 - 1))
133
	    {
134
	    case 0:
135
		do
136
		  {
137
		      HASHC;
138
	    case 7:
139
		      HASHC;
140
	    case 6:
141
		      HASHC;
142
	    case 5:
143
		      HASHC;
144
	    case 4:
145
		      HASHC;
146
	    case 3:
147
		      HASHC;
148
	    case 2:
149
		      HASHC;
150
	    case 1:
151
		      HASHC;
152
		  }
153
		while (--loop);
154
	    }
155
156
      }
157
#else
158
    while (len--)
159
	n = *str++ + 65599 * n;
160
#endif
161
    return n;
162
}
163
164
/*
165
 * check page sanity:
166
 * number of entries should be something
167
 * reasonable, and all offsets in the index should be in order.
168
 * this could be made more rigorous.
169
 */
170
static int chkpage (char *pag)
171
{
172
    int     n;
173
    int     off;
174
    short  *ino = (short *) pag;
175
176
    if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof (short))
177
	        return 0;
178
179
    if (n > 0)
180
      {
181
	  off = PBLKSIZ;
182
	  for (ino++; n > 0; ino += 2)
183
	    {
184
		if (ino[0] > off || ino[1] > off ||
185
		    ino[1] > ino[0])
186
		    return 0;
187
		off = ino[1];
188
		n -= 2;
189
	    }
190
      }
191
    return 1;
192
}
193
194
/*
195
 * search for the key in the page.
196
 * return offset index in the range 0 < i < n.
197
 * return 0 if not found.
198
 */
199
static int seepair (char *pag, int n, char *key, int siz)
200
{
201
    int     i;
202
    int     off = PBLKSIZ;
203
    short  *ino = (short *) pag;
204
205
    for (i = 1; i < n; i += 2)
206
      {
207
	  if (siz == off - ino[i] &&
208
	      memcmp (key, pag + ino[i], siz) == 0)
209
	      return i;
210
	  off = ino[i + 1];
211
      }
212
    return 0;
213
}
214
215
#ifdef SEEDUPS
216
static int duppair (char *pag, datum key)
217
{
218
    short  *ino = (short *) pag;
219
220
    return ino[0] > 0 && seepair (pag, ino[0], key.dptr, key.dsize) > 0;
221
}
222
223
#endif
224
225
/* ************************* */
226
227
/*
228
 * sdbm - ndbm work-alike hashed database library
229
 * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
230
 * author: oz@nexus.yorku.ca
231
 * status: public domain.
232
 *
233
 * page-level routines
234
 */
235
236
/*
237
 * page format:
238
 *      +------------------------------+
239
 * ino  | n | keyoff | datoff | keyoff |
240
 *      +------------+--------+--------+
241
 *      | datoff | - - - ---->         |
242
 *      +--------+---------------------+
243
 *      |        F R E E A R E A       |
244
 *      +--------------+---------------+
245
 *      |  <---- - - - | data          |
246
 *      +--------+-----+----+----------+
247
 *      |  key   | data     | key      |
248
 *      +--------+----------+----------+
249
 *
250
 * calculating the offsets for free area:  if the number
251
 * of entries (ino[0]) is zero, the offset to the END of
252
 * the free area is the block size. Otherwise, it is the
253
 * nth (ino[ino[0]]) entry's offset.
254
 */
255
256
static int fitpair (char *pag, int need)
257
{
258
    int     n;
259
    int     off;
260
    int     avail;
261
    short  *ino = (short *) pag;
262
263
    off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
264
    avail = off - (n + 1) * sizeof (short);
265
    need += 2 * sizeof (short);
266
267
    return need <= avail;
268
}
269
270
static void putpair (char *pag, datum key, datum val)
271
{
272
    int     n;
273
    int     off;
274
    short  *ino = (short *) pag;
275
276
    off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
277
/*
278
 * enter the key first
279
 */
280
    off -= key.dsize;
281
    (void) memcpy (pag + off, key.dptr, key.dsize);
282
    ino[n + 1] = off;
283
/*
284
 * now the data
285
 */
286
    off -= val.dsize;
287
    (void) memcpy (pag + off, val.dptr, val.dsize);
288
    ino[n + 2] = off;
289
/*
290
 * adjust item count
291
 */
292
    ino[0] += 2;
293
}
294
295
static datum getpair (char *pag, datum key)
296
{
297
    int     i;
298
    int     n;
299
    datum   val;
300
    short  *ino = (short *) pag;
301
302
    if ((n = ino[0]) == 0)
303
	return nullitem;
304
305
    if ((i = seepair (pag, n, key.dptr, key.dsize)) == 0)
306
	return nullitem;
307
308
    val.dptr = pag + ino[i + 1];
309
    val.dsize = ino[i] - ino[i + 1];
310
    return val;
311
}
312
313
static datum getnkey (char *pag, int num)
314
{
315
    datum   key;
316
    int     off;
317
    short  *ino = (short *) pag;
318
319
    num = num * 2 - 1;
320
    if (ino[0] == 0 || num > ino[0])
321
	return nullitem;
322
323
    off = (num > 1) ? ino[num - 1] : PBLKSIZ;
324
325
    key.dptr = pag + ino[num];
326
    key.dsize = off - ino[num];
327
328
    return key;
329
}
330
331
static int delpair (char *pag, datum key)
332
{
333
    int     n;
334
    int     i;
335
    short  *ino = (short *) pag;
336
337
    if ((n = ino[0]) == 0)
338
	return 0;
339
340
    if ((i = seepair (pag, n, key.dptr, key.dsize)) == 0)
341
	return 0;
342
/*
343
 * found the key. if it is the last entry
344
 * [i.e. i == n - 1] we just adjust the entry count.
345
 * hard case: move all data down onto the deleted pair,
346
 * shift offsets onto deleted offsets, and adjust them.
347
 * [note: 0 < i < n]
348
 */
349
    if (i < n - 1)
350
      {
351
	  int     m;
352
	  char   *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
353
	  char   *src = pag + ino[i + 1];
354
	  int     zoo = dst - src;
355
356
/*
357
 * shift data/keys down
358
 */
359
	  m = ino[i + 1] - ino[n];
360
#ifdef DUFF
361
#define MOVB    *--dst = *--src
362
	  if (m > 0)
363
	    {
364
		int     loop = (m + 8 - 1) >> 3;
365
366
		switch (m & (8 - 1))
367
		  {
368
		  case 0:
369
		      do
370
			{
371
			    MOVB;
372
		  case 7:
373
			    MOVB;
374
		  case 6:
375
			    MOVB;
376
		  case 5:
377
			    MOVB;
378
		  case 4:
379
			    MOVB;
380
		  case 3:
381
			    MOVB;
382
		  case 2:
383
			    MOVB;
384
		  case 1:
385
			    MOVB;
386
			}
387
		      while (--loop);
388
		  }
389
	    }
390
#else
391
	  dst -= m;
392
	  src -= m;
393
	  memmove (dst, src, m);
394
#endif
395
/*
396
 * adjust offset index up
397
 */
398
	  while (i < n - 1)
399
	    {
400
		ino[i] = ino[i + 2] + zoo;
401
		i++;
402
	    }
403
      }
404
    ino[0] -= 2;
405
    return 1;
406
}
407
408
static void splpage (char *pag, char *new, long sbit)
409
{
410
    datum   key;
411
    datum   val;
412
413
    int     n;
414
    int     off = PBLKSIZ;
415
    char    cur[PBLKSIZ];
416
    short  *ino = (short *) cur;
417
418
    (void) memcpy (cur, pag, PBLKSIZ);
419
    (void) memset (pag, 0, PBLKSIZ);
420
    (void) memset (new, 0, PBLKSIZ);
421
422
    n = ino[0];
423
    for (ino++; n > 0; ino += 2)
424
      {
425
	  key.dptr = cur + ino[0];
426
	  key.dsize = off - ino[0];
427
	  val.dptr = cur + ino[1];
428
	  val.dsize = ino[0] - ino[1];
429
/*
430
 * select the page pointer (by looking at sbit) and insert
431
 */
432
	  (void) putpair ((exhash (key) & sbit) ? new : pag, key, val);
433
434
	  off = ino[1];
435
	  n -= 2;
436
      }
437
}
438
439
static int getdbit (DBM * db, long dbit)
440
{
441
    long    c;
442
    long    dirb;
443
444
    c = dbit / BYTESIZ;
445
    dirb = c / DBLKSIZ;
446
447
    if (dirb != db->dirbno)
448
      {
449
	  int got;
450
	  if (lseek (db->dirf, OFF_DIR (dirb), SEEK_SET) < 0
451
	      || (got = read(db->dirf, db->dirbuf, DBLKSIZ)) < 0)
452
	      return 0;
453
	  if (got==0)
454
              memset(db->dirbuf,0,DBLKSIZ);
455
	  db->dirbno = dirb;
456
      }
457
458
    return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
459
}
460
461
static int setdbit (DBM * db, long dbit)
462
{
463
    long    c;
464
    long    dirb;
465
466
    c = dbit / BYTESIZ;
467
    dirb = c / DBLKSIZ;
468
469
    if (dirb != db->dirbno)
470
      {
471
	  int got;
472
	  if (lseek (db->dirf, OFF_DIR (dirb), SEEK_SET) < 0
473
	      || (got = read(db->dirf, db->dirbuf, DBLKSIZ)) < 0)
474
	      return 0;
475
	  if (got==0)
476
              memset(db->dirbuf,0,DBLKSIZ);
477
	  db->dirbno = dirb;
478
      }
479
480
    db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
481
482
#if 0
483
    if (dbit >= db->maxbno)
484
	db->maxbno += DBLKSIZ * BYTESIZ;
485
#else
486
    if (OFF_DIR((dirb+1))*BYTESIZ > db->maxbno)
487
        db->maxbno=OFF_DIR((dirb+1))*BYTESIZ;
488
#endif
489
490
    if (lseek (db->dirf, OFF_DIR (dirb), SEEK_SET) < 0
491
	|| write (db->dirf, db->dirbuf, DBLKSIZ) < 0)
492
	return 0;
493
494
    return 1;
495
}
496
497
/*
498
 * getnext - get the next key in the page, and if done with
499
 * the page, try the next page in sequence
500
 */
501
static datum getnext (DBM * db)
502
{
503
    datum   key;
504
505
    for (;;)
506
      {
507
	  db->keyptr++;
508
	  key = getnkey (db->pagbuf, db->keyptr);
509
	  if (key.dptr != NULL)
510
	      return key;
511
/*
512
 * we either run out, or there is nothing on this page..
513
 * try the next one... If we lost our position on the
514
 * file, we will have to seek.
515
 */
516
	  db->keyptr = 0;
517
	  if (db->pagbno != db->blkptr++)
518
	      if (lseek (db->pagf, OFF_PAG (db->blkptr), SEEK_SET) < 0)
519
		  break;
520
	  db->pagbno = db->blkptr;
521
	  if (read (db->pagf, db->pagbuf, PBLKSIZ) <= 0)
522
	      break;
523
	  if (!chkpage (db->pagbuf))
524
	      break;
525
      }
526
527
    return ioerr (db), nullitem;
528
}
529
530
/*
531
 * all important binary trie traversal
532
 */
533
static int getpage (DBM * db, long hash)
534
{
535
    int     hbit;
536
    long    dbit;
537
    long    pagb;
538
539
    dbit = 0;
540
    hbit = 0;
541
    while (dbit < db->maxbno && getdbit (db, dbit))
542
	dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
543
544
    db->curbit = dbit;
545
    db->hmask = masks[hbit];
546
547
    pagb = hash & db->hmask;
548
/*
549
 * see if the block we need is already in memory.
550
 * note: this lookaside cache has about 10% hit rate.
551
 */
552
    if (pagb != db->pagbno)
553
      {
554
/*
555
 * note: here, we assume a "hole" is read as 0s.
556
 * if not, must zero pagbuf first.
557
 */
558
	  if (lseek (db->pagf, OFF_PAG (pagb), SEEK_SET) < 0
559
	      || read (db->pagf, db->pagbuf, PBLKSIZ) < 0)
560
	      return 0;
561
	  if (!chkpage (db->pagbuf))
562
	      return 0;
563
	  db->pagbno = pagb;
564
      }
565
    return 1;
566
}
567
568
/*
569
 * makroom - make room by splitting the overfull page
570
 * this routine will attempt to make room for SPLTMAX times before
571
 * giving up.
572
 */
573
static int makroom (DBM * db, long hash, int need)
574
{
575
    long    newp;
576
    char    twin[PBLKSIZ];
577
    char   *pag = db->pagbuf;
578
    char   *new = twin;
579
    int     smax = SPLTMAX;
580
581
    do
582
      {
583
/*
584
 * split the current page
585
 */
586
	  (void) splpage (pag, new, db->hmask + 1);
587
/*
588
 * address of the new page
589
 */
590
	  newp = (hash & db->hmask) | (db->hmask + 1);
591
592
/*
593
 * write delay, read avoidence/cache shuffle:
594
 * select the page for incoming pair: if key is to go to the new page,
595
 * write out the previous one, and copy the new one over, thus making
596
 * it the current page. If not, simply write the new page, and we are
597
 * still looking at the page of interest. current page is not updated
598
 * here, as sdbm_store will do so, after it inserts the incoming pair.
599
 */
600
	  if (hash & (db->hmask + 1))
601
	    {
602
		if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
603
		    || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
604
		    return 0;
605
		db->pagbno = newp;
606
		(void) memcpy (pag, new, PBLKSIZ);
607
	    }
608
	  else if (lseek (db->pagf, OFF_PAG (newp), SEEK_SET) < 0
609
		   || write (db->pagf, new, PBLKSIZ) < 0)
610
	      return 0;
611
612
	  if (!setdbit (db, db->curbit))
613
	      return 0;
614
/*
615
 * see if we have enough room now
616
 */
617
	  if (fitpair (pag, need))
618
	      return 1;
619
/*
620
 * try again... update curbit and hmask as getpage would have
621
 * done. because of our update of the current page, we do not
622
 * need to read in anything. BUT we have to write the current
623
 * [deferred] page out, as the window of failure is too great.
624
 */
625
	  db->curbit = 2 * db->curbit +
626
	      ((hash & (db->hmask + 1)) ? 2 : 1);
627
	  db->hmask |= db->hmask + 1;
628
629
	  if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
630
	      || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
631
	      return 0;
632
633
      }
634
    while (--smax);
635
/*
636
 * if we are here, this is real bad news. After SPLTMAX splits,
637
 * we still cannot fit the key. say goodnight.
638
 */
639
#ifdef BADMESS
640
    (void) write (2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
641
#endif
642
    return 0;
643
644
}
645
646
static SDBM *sdbm_prep (char *dirname, char *pagname, int flags, int mode)
647
{
648
    SDBM   *db;
649
    struct stat dstat;
650
651
    if ((db = (SDBM *) mymalloc (sizeof (SDBM))) == NULL)
652
	return errno = ENOMEM, (SDBM *) NULL;
653
654
    db->flags = 0;
655
    db->blkptr = 0;
656
    db->keyptr = 0;
657
/*
658
 * adjust user flags so that WRONLY becomes RDWR,
659
 * as required by this package. Also set our internal
660
 * flag for RDONLY if needed.
661
 */
662
    if (flags & O_WRONLY)
663
	flags = (flags & ~O_WRONLY) | O_RDWR;
664
    else if ((flags & 03) == O_RDONLY)
665
	db->flags = DBM_RDONLY;
666
#if defined(OS2) || defined(MSDOS) || defined(WIN32)
667
    flags |= O_BINARY;
668
#endif
669
670
/*
671
 * Make sure to ignore the O_EXCL option, as the file might exist due
672
 * to the locking.
673
 */
674
    flags &= ~O_EXCL;
675
676
/*
677
 * open the files in sequence, and stat the dirfile.
678
 * If we fail anywhere, undo everything, return NULL.
679
 */
680
681
    if ((db->pagf = open (pagname, flags, mode)) > -1)
682
      {
683
	  if ((db->dirf = open (dirname, flags, mode)) > -1)
684
	    {
685
/*
686
 * need the dirfile size to establish max bit number.
687
 */
688
		if (fstat (db->dirf, &dstat) == 0)
689
		  {
690
		      /*
691
                       * success
692
                       */
693
		      return db;
694
		  }
695
		msg_info ("closing dirf");
696
		(void) close (db->dirf);
697
	    }
698
	  msg_info ("closing pagf");
699
	  (void) close (db->pagf);
700
      }
701
    myfree ((char *) db);
702
    return (SDBM *) NULL;
703
}
704
705
static DBM *sdbm_internal_open (SDBM * sdbm)
706
{
707
    DBM    *db;
708
    struct stat dstat;
709
710
    if ((db = (DBM *) mymalloc (sizeof (DBM))) == NULL)
711
	return errno = ENOMEM, (DBM *) NULL;
712
713
    db->flags = sdbm->flags;
714
    db->hmask = 0;
715
    db->blkptr = sdbm->blkptr;
716
    db->keyptr = sdbm->keyptr;
717
    db->pagf = sdbm->pagf;
718
    db->dirf = sdbm->dirf;
719
    db->pagbuf = sdbm->pagbuf;
720
    db->dirbuf = sdbm->dirbuf;
721
722
/*
723
 * need the dirfile size to establish max bit number.
724
 */
725
    if (fstat (db->dirf, &dstat) == 0)
726
      {
727
/*
728
 * zero size: either a fresh database, or one with a single,
729
 * unsplit data page: dirpage is all zeros.
730
 */
731
	  db->dirbno = (!dstat.st_size) ? 0 : -1;
732
	  db->pagbno = -1;
733
	  db->maxbno = dstat.st_size * BYTESIZ;
734
735
	  (void) memset (db->pagbuf, 0, PBLKSIZ);
736
	  (void) memset (db->dirbuf, 0, DBLKSIZ);
737
	  return db;
738
      }
739
    myfree ((char *) db);
740
    return (DBM *) NULL;
741
}
742
743
static void sdbm_internal_close (DBM * db)
744
{
745
    if (db == NULL)
746
	errno = EINVAL;
747
    else
748
      {
749
	  myfree ((char *) db);
750
      }
751
}
752
753
datum   sdbm_fetch (SDBM * sdb, datum key)
754
{
755
    datum   retval;
756
    DBM    *db;
757
758
    if (sdb == NULL || bad (key))
759
	return errno = EINVAL, nullitem;
760
761
    if (!(db = sdbm_internal_open (sdb)))
762
	return errno = EINVAL, nullitem;
763
764
    if (getpage (db, exhash (key)))
765
      {
766
	  retval = getpair (db->pagbuf, key);
767
	  sdbm_internal_close (db);
768
	  return retval;
769
      }
770
771
    sdbm_internal_close (db);
772
773
    return ioerr (sdb), nullitem;
774
}
775
776
int     sdbm_delete (SDBM * sdb, datum key)
777
{
778
    int     retval;
779
    DBM    *db;
780
781
    if (sdb == NULL || bad (key))
782
	return errno = EINVAL, -1;
783
    if (sdbm_rdonly (sdb))
784
	return errno = EPERM, -1;
785
786
    if (!(db = sdbm_internal_open (sdb)))
787
	return errno = EINVAL, -1;
788
789
    if (getpage (db, exhash (key)))
790
      {
791
	  if (!delpair (db->pagbuf, key))
792
	      retval = -1;
793
/*
794
 * update the page file
795
 */
796
	  else if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
797
		   || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
798
	      retval = ioerr (sdb), -1;
799
	  else
800
	      retval = 0;
801
      }
802
    else
803
	retval = ioerr (sdb), -1;
804
805
    sdbm_internal_close (db);
806
807
    return retval;
808
}
809
810
int     sdbm_store (SDBM * sdb, datum key, datum val, int flags)
811
{
812
    int     need;
813
    int     retval;
814
    long    hash;
815
    DBM    *db;
816
817
    if (sdb == NULL || bad (key))
818
	return errno = EINVAL, -1;
819
    if (sdbm_rdonly (sdb))
820
	return errno = EPERM, -1;
821
822
    need = key.dsize + val.dsize;
823
/*
824
 * is the pair too big (or too small) for this database ??
825
 */
826
    if (need < 0 || need > PAIRMAX)
827
	return errno = EINVAL, -1;
828
829
    if (!(db = sdbm_internal_open (sdb)))
830
	return errno = EINVAL, -1;
831
832
    if (getpage (db, (hash = exhash (key))))
833
      {
834
/*
835
 * if we need to replace, delete the key/data pair
836
 * first. If it is not there, ignore.
837
 */
838
	  if (flags == DBM_REPLACE)
839
	      (void) delpair (db->pagbuf, key);
840
#ifdef SEEDUPS
841
	  else if (duppair (db->pagbuf, key))
842
	    {
843
		sdbm_internal_close (db);
844
		return 1;
845
	    }
846
#endif
847
/*
848
 * if we do not have enough room, we have to split.
849
 */
850
	  if (!fitpair (db->pagbuf, need))
851
	      if (!makroom (db, hash, need))
852
		{
853
		    sdbm_internal_close (db);
854
		    return ioerr (db), -1;
855
		}
856
/*
857
 * we have enough room or split is successful. insert the key,
858
 * and update the page file.
859
 */
860
	  (void) putpair (db->pagbuf, key, val);
861
862
	  if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
863
	      || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
864
	    {
865
		sdbm_internal_close (db);
866
		return ioerr (db), -1;
867
	    }
868
	  /*
869
           * success
870
           */
871
	  sdbm_internal_close (db);
872
	  return 0;
873
      }
874
875
    sdbm_internal_close (db);
876
    return ioerr (sdb), -1;
877
}
878
879
/*
880
 * the following two routines will break if
881
 * deletions aren't taken into account. (ndbm bug)
882
 */
883
datum   sdbm_firstkey (SDBM * sdb)
884
{
885
    datum   retval;
886
    DBM    *db;
887
888
    if (sdb == NULL)
889
	return errno = EINVAL, nullitem;
890
891
    if (!(db = sdbm_internal_open (sdb)))
892
	return errno = EINVAL, nullitem;
893
894
/*
895
 * start at page 0
896
 */
897
    if (lseek (db->pagf, OFF_PAG (0), SEEK_SET) < 0
898
	|| read (db->pagf, db->pagbuf, PBLKSIZ) < 0)
899
      {
900
	  sdbm_internal_close (db);
901
	  return ioerr (sdb), nullitem;
902
      }
903
    db->pagbno = 0;
904
    db->blkptr = 0;
905
    db->keyptr = 0;
906
907
    retval = getnext (db);
908
    sdb->blkptr = db->blkptr;
909
    sdb->keyptr = db->keyptr;
910
    sdbm_internal_close (db);
911
    return retval;
912
}
913
914
datum   sdbm_nextkey (SDBM * sdb)
915
{
916
    datum   retval;
917
    DBM    *db;
918
919
    if (sdb == NULL)
920
	return errno = EINVAL, nullitem;
921
922
    if (!(db = sdbm_internal_open (sdb)))
923
	return errno = EINVAL, nullitem;
924
925
    retval = getnext (db);
926
    sdb->blkptr = db->blkptr;
927
    sdb->keyptr = db->keyptr;
928
    sdbm_internal_close (db);
929
    return retval;
930
}
931
932
void    sdbm_close (SDBM * db)
933
{
934
    if (db == NULL)
935
	errno = EINVAL;
936
    else
937
      {
938
	  (void) close (db->dirf);
939
	  (void) close (db->pagf);
940
	  myfree ((char *) db);
941
      }
942
}
943
944
SDBM   *sdbm_open (char *file, int flags, int mode)
945
{
946
    SDBM   *db;
947
    char   *dirname;
948
    char   *pagname;
949
    int     n;
950
951
    if (file == NULL || !*file)
952
	return errno = EINVAL, (SDBM *) NULL;
953
/*
954
 * need space for two seperate filenames
955
 */
956
    n = strlen (file) * 2 + strlen (DIRFEXT) + strlen (PAGFEXT) + 2;
957
958
    if ((dirname = (char *) mymalloc ((unsigned) n)) == NULL)
959
	return errno = ENOMEM, (SDBM *) NULL;
960
/*
961
 * build the file names
962
 */
963
    dirname = strcat (strcpy (dirname, file), DIRFEXT);
964
    pagname = strcpy (dirname + strlen (dirname) + 1, file);
965
    pagname = strcat (pagname, PAGFEXT);
966
967
    db = sdbm_prep (dirname, pagname, flags, mode);
968
    myfree ((char *) dirname);
969
    return db;
970
}
971
(-)postfix-1.1.11-20020613-orig/src/util/sdbm.h (+97 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*      sdbm 3h
4
/* SUMMARY
5
/*      SDBM Simple DBM: ndbm work-alike hashed database library
6
/* SYNOPSIS
7
/*      include "sdbm.h"
8
/* DESCRIPTION
9
/* .nf
10
/*--*/
11
12
#ifndef UTIL_SDBM_H
13
#define UTIL_SDBM_H
14
15
/*
16
 * sdbm - ndbm work-alike hashed database library
17
 * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
18
 * author: oz@nexus.yorku.ca
19
 * status: public domain.
20
 */
21
22
#define DUFF    /* go ahead and use the loop-unrolled version */
23
24
#include <stdio.h>
25
26
#define DBLKSIZ 16384                   /* SSL cert chains require more */
27
#define PBLKSIZ 8192                    /* SSL cert chains require more */
28
#define PAIRMAX 8008                    /* arbitrary on PBLKSIZ-N */
29
#define SPLTMAX 10                      /* maximum allowed splits */
30
                                        /* for a single insertion */
31
#define DIRFEXT ".dir"
32
#define PAGFEXT ".pag"
33
34
typedef struct {
35
        int dirf;                      /* directory file descriptor */
36
        int pagf;                      /* page file descriptor */
37
        int flags;                     /* status/error flags, see below */
38
        long blkptr;                   /* current block for nextkey */
39
        int keyptr;                    /* current key for nextkey */
40
        char pagbuf[PBLKSIZ];          /* page file block buffer */
41
        char dirbuf[DBLKSIZ];          /* directory file block buffer */
42
} SDBM;
43
44
#define DBM_RDONLY      0x1            /* data base open read-only */
45
#define DBM_IOERR       0x2            /* data base I/O error */
46
47
/*
48
 * utility macros
49
 */
50
#define sdbm_rdonly(db)         ((db)->flags & DBM_RDONLY)
51
#define sdbm_error(db)          ((db)->flags & DBM_IOERR)
52
53
#define sdbm_clearerr(db)       ((db)->flags &= ~DBM_IOERR)  /* ouch */
54
55
#define sdbm_dirfno(db) ((db)->dirf)
56
#define sdbm_pagfno(db) ((db)->pagf)
57
58
typedef struct {
59
        char *dptr;
60
        int dsize;
61
} datum;
62
63
extern datum nullitem;
64
65
/*
66
 * flags to sdbm_store
67
 */
68
#define DBM_INSERT      0
69
#define DBM_REPLACE     1
70
71
/*
72
 * ndbm interface
73
 */
74
extern SDBM *sdbm_open(char *, int, int);
75
extern void sdbm_close(SDBM *);
76
extern datum sdbm_fetch(SDBM *, datum);
77
extern int sdbm_delete(SDBM *, datum);
78
extern int sdbm_store(SDBM *, datum, datum, int);
79
extern datum sdbm_firstkey(SDBM *);
80
extern datum sdbm_nextkey(SDBM *);
81
82
/*
83
 * sdbm - ndbm work-alike hashed database library
84
 * tuning and portability constructs [not nearly enough]
85
 * author: oz@nexus.yorku.ca
86
 */
87
88
#define BYTESIZ         8
89
90
/*
91
 * important tuning parms (hah)
92
 */
93
94
#define SEEDUPS                 /* always detect duplicates */
95
#define BADMESS                 /* generate a message for worst case:
96
                                   cannot make room after SPLTMAX splits */
97
#endif /* UTIL_SDBM_H */
(-)postfix-1.1.11-20020613-orig/src/util/sys_defs.h (+4 lines)
Lines 73-78 Link Here
73
#define DEF_MAILBOX_LOCK "flock, dotlock"
73
#define DEF_MAILBOX_LOCK "flock, dotlock"
74
#endif
74
#endif
75
75
76
#if ((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) || defined(USAGI_LIBINET6))
77
#define HAVE_GETIFADDRS
78
#endif
79
76
 /*
80
 /*
77
  * UNIX on MAC.
81
  * UNIX on MAC.
78
  */
82
  */
(-)postfix-1.1.11-20020613-orig/src/util/valid_hostname.c (-1 / +38 lines)
Lines 47-52 Link Here
47
#include <string.h>
47
#include <string.h>
48
#include <ctype.h>
48
#include <ctype.h>
49
49
50
#ifdef INET6
51
#include <netinet/in.h>
52
#include <sys/socket.h>
53
#include <arpa/inet.h>
54
#include <netdb.h>
55
#endif
56
50
/* Utility library. */
57
/* Utility library. */
51
58
52
#include "msg.h"
59
#include "msg.h"
Lines 103-109 Link Here
103
		    msg_warn("%s: misplaced hyphen: %.100s", myname, name);
110
		    msg_warn("%s: misplaced hyphen: %.100s", myname, name);
104
		return (0);
111
		return (0);
105
	    }
112
	    }
106
	} else {
113
	}
114
#ifdef INET6
115
	else if (ch == ':') {
116
	    struct addrinfo hints, *res;
117
118
	    memset(&hints, 0, sizeof(hints));
119
	    hints.ai_family = AF_INET6;
120
	    hints.ai_socktype = SOCK_STREAM;	/*dummy*/
121
	    hints.ai_flags = AI_NUMERICHOST;
122
	    if (getaddrinfo(name, "0", &hints, &res) == 0) {
123
		freeaddrinfo(res);
124
		return 1;
125
	    } else
126
		return 0;
127
	}
128
#endif
129
	else {
107
	    if (gripe)
130
	    if (gripe)
108
		msg_warn("%s: invalid character %d(decimal): %.100s",
131
		msg_warn("%s: invalid character %d(decimal): %.100s",
109
			 myname, ch, name);
132
			 myname, ch, name);
Lines 135-140 Link Here
135
    int     byte_count = 0;
158
    int     byte_count = 0;
136
    int     byte_val = 0;
159
    int     byte_val = 0;
137
    int     ch;
160
    int     ch;
161
#ifdef INET6
162
    struct addrinfo hints, *res;
163
#endif
138
164
139
#define BYTES_NEEDED	4
165
#define BYTES_NEEDED	4
140
166
Lines 146-151 Link Here
146
	    msg_warn("%s: empty address", myname);
172
	    msg_warn("%s: empty address", myname);
147
	return (0);
173
	return (0);
148
    }
174
    }
175
176
#ifdef INET6
177
    memset(&hints, 0, sizeof(hints));
178
    hints.ai_family = AF_INET6;
179
    hints.ai_socktype = SOCK_STREAM;	/*dummy*/
180
    hints.ai_flags = AI_NUMERICHOST;
181
    if (getaddrinfo(addr, "0", &hints, &res) == 0) {
182
	freeaddrinfo(res);
183
	return 1;
184
    }
185
#endif
149
186
150
    /*
187
    /*
151
     * Scary code to avoid sscanf() overflow nasties.
188
     * Scary code to avoid sscanf() overflow nasties.

Return to bug 5023