No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / smtpd / smtpd_sasl_proto.c
blob0c270fad14801806c0ef7ea1f40da692efe976e2
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* smtpd_sasl_proto 3
6 /* SUMMARY
7 /* Postfix SMTP protocol support for SASL authentication
8 /* SYNOPSIS
9 /* #include "smtpd.h"
10 /* #include "smtpd_sasl_proto.h"
12 /* void smtpd_sasl_auth_cmd(state, argc, argv)
13 /* SMTPD_STATE *state;
14 /* int argc;
15 /* SMTPD_TOKEN *argv;
17 /* void smtpd_sasl_auth_reset(state)
18 /* SMTPD_STATE *state;
20 /* char *smtpd_sasl_mail_opt(state, sender)
21 /* SMTPD_STATE *state;
22 /* const char *sender;
24 /* void smtpd_sasl_mail_log(state)
25 /* SMTPD_STATE *state;
27 /* void smtpd_sasl_mail_reset(state)
28 /* SMTPD_STATE *state;
30 /* static int permit_sasl_auth(state, authenticated, unauthenticated)
31 /* SMTPD_STATE *state;
32 /* int authenticated;
33 /* int unauthenticated;
34 /* DESCRIPTION
35 /* This module contains random chunks of code that implement
36 /* the SMTP protocol interface for SASL negotiation. The goal
37 /* is to reduce clutter of the main SMTP server source code.
39 /* smtpd_sasl_auth_cmd() implements the AUTH command and updates
40 /* the following state structure members:
41 /* .IP sasl_method
42 /* The authentication method that was successfully applied.
43 /* This member is a null pointer in the absence of successful
44 /* authentication.
45 /* .IP sasl_username
46 /* The username that was successfully authenticated.
47 /* This member is a null pointer in the absence of successful
48 /* authentication.
49 /* .PP
50 /* smtpd_sasl_auth_reset() cleans up after the AUTH command.
51 /* This is required before smtpd_sasl_auth_cmd() can be used again.
53 /* smtpd_sasl_mail_opt() implements the SASL-specific AUTH=sender
54 /* option to the MAIL FROM command. The result is an error response
55 /* in case of problems.
57 /* smtpd_sasl_mail_log() logs SASL-specific information after
58 /* processing the MAIL FROM command.
60 /* smtpd_sasl_mail_reset() performs cleanup for the SASL-specific
61 /* AUTH=sender option to the MAIL FROM command.
63 /* permit_sasl_auth() permits access from an authenticated client.
64 /* This test fails for clients that use anonymous authentication.
66 /* Arguments:
67 /* .IP state
68 /* SMTP session context.
69 /* .IP argc
70 /* Number of command line tokens.
71 /* .IP argv
72 /* The command line parsed into tokens.
73 /* .IP sender
74 /* Sender address from the AUTH=sender option in the MAIL FROM
75 /* command.
76 /* .IP authenticated
77 /* Result for authenticated client.
78 /* .IP unauthenticated
79 /* Result for unauthenticated client.
80 /* DIAGNOSTICS
81 /* All errors are fatal.
82 /* LICENSE
83 /* .ad
84 /* .fi
85 /* The Secure Mailer license must be distributed with this software.
86 /* AUTHOR(S)
87 /* Initial implementation by:
88 /* Till Franke
89 /* SuSE Rhein/Main AG
90 /* 65760 Eschborn, Germany
92 /* Adopted by:
93 /* Wietse Venema
94 /* IBM T.J. Watson Research
95 /* P.O. Box 704
96 /* Yorktown Heights, NY 10598, USA
98 /* TLS support originally by:
99 /* Lutz Jaenicke
100 /* BTU Cottbus
101 /* Allgemeine Elektrotechnik
102 /* Universitaetsplatz 3-4
103 /* D-03044 Cottbus, Germany
104 /*--*/
106 /* System library. */
108 #include <sys_defs.h>
109 #include <string.h>
111 #ifdef STRCASECMP_IN_STRINGS_H
112 #include <strings.h>
113 #endif
115 /* Utility library. */
117 #include <msg.h>
118 #include <mymalloc.h>
119 #include <stringops.h>
121 /* Global library. */
123 #include <mail_params.h>
124 #include <mail_proto.h>
125 #include <mail_error.h>
126 #include <ehlo_mask.h>
128 /* Application-specific. */
130 #include "smtpd.h"
131 #include "smtpd_token.h"
132 #include "smtpd_chat.h"
133 #include "smtpd_sasl_proto.h"
134 #include "smtpd_sasl_glue.h"
136 #ifdef USE_SASL_AUTH
138 /* smtpd_sasl_auth_cmd - process AUTH command */
140 int smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
142 char *auth_mechanism;
143 char *initial_response;
144 const char *err;
146 if (var_helo_required && state->helo_name == 0) {
147 state->error_mask |= MAIL_ERROR_POLICY;
148 smtpd_chat_reply(state, "503 5.5.1 Error: send HELO/EHLO first");
149 return (-1);
151 if (SMTPD_STAND_ALONE(state) || !smtpd_sasl_is_active(state)
152 || (state->ehlo_discard_mask & EHLO_MASK_AUTH)) {
153 state->error_mask |= MAIL_ERROR_PROTOCOL;
154 smtpd_chat_reply(state, "503 5.5.1 Error: authentication not enabled");
155 return (-1);
157 if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0) {
158 if (err[0] == '5') {
159 state->error_mask |= MAIL_ERROR_POLICY;
160 smtpd_chat_reply(state, "%s", err);
161 return (-1);
163 /* Sendmail compatibility: map 4xx into 454. */
164 else if (err[0] == '4') {
165 state->error_mask |= MAIL_ERROR_POLICY;
166 smtpd_chat_reply(state, "454 4.3.0 Try again later");
167 return (-1);
170 #ifdef USE_TLS
171 if (state->tls_auth_only && !state->tls_context) {
172 state->error_mask |= MAIL_ERROR_PROTOCOL;
173 /* RFC 4954, Section 4. */
174 smtpd_chat_reply(state, "504 5.5.4 Encryption required for requested authentication mechanism");
175 return (-1);
177 #endif
178 if (state->sasl_username) {
179 state->error_mask |= MAIL_ERROR_PROTOCOL;
180 smtpd_chat_reply(state, "503 5.5.1 Error: already authenticated");
181 return (-1);
183 if (argc < 2 || argc > 3) {
184 state->error_mask |= MAIL_ERROR_PROTOCOL;
185 smtpd_chat_reply(state, "501 5.5.4 Syntax: AUTH mechanism");
186 return (-1);
190 * All authentication failures shall be logged. The 5xx reply code from
191 * the SASL authentication routine triggers tar-pit delays, which help to
192 * slow down password guessing attacks.
194 auth_mechanism = argv[1].strval;
195 initial_response = (argc == 3 ? argv[2].strval : 0);
196 return (smtpd_sasl_authenticate(state, auth_mechanism, initial_response));
199 /* smtpd_sasl_auth_reset - clean up after AUTH command */
201 void smtpd_sasl_auth_reset(SMTPD_STATE *state)
203 smtpd_sasl_logout(state);
206 /* smtpd_sasl_mail_opt - SASL-specific MAIL FROM option */
208 char *smtpd_sasl_mail_opt(SMTPD_STATE *state, const char *addr)
212 * Do not store raw RFC2554 protocol data.
214 if (!smtpd_sasl_is_active(state)) {
215 state->error_mask |= MAIL_ERROR_PROTOCOL;
216 return ("503 5.5.4 Error: authentication disabled");
218 #if 0
219 if (state->sasl_username == 0) {
220 state->error_mask |= MAIL_ERROR_PROTOCOL;
221 return ("503 5.5.4 Error: send AUTH command first");
223 #endif
224 if (state->sasl_sender != 0) {
225 state->error_mask |= MAIL_ERROR_PROTOCOL;
226 return ("503 5.5.4 Error: multiple AUTH= options");
228 if (strcmp(addr, "<>") != 0) {
229 state->sasl_sender = mystrdup(addr);
230 printable(state->sasl_sender, '?');
232 return (0);
235 /* smtpd_sasl_mail_log - SASL-specific MAIL FROM logging */
237 void smtpd_sasl_mail_log(SMTPD_STATE *state)
239 #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
241 msg_info("%s: client=%s%s%s%s%s%s%s",
242 state->queue_id ? state->queue_id : "NOQUEUE", FORWARD_NAMADDR(state),
243 IFELSE(state->sasl_method, ", sasl_method=", ""),
244 IFELSE(state->sasl_method, state->sasl_method, ""),
245 IFELSE(state->sasl_username, ", sasl_username=", ""),
246 IFELSE(state->sasl_username, state->sasl_username, ""),
247 IFELSE(state->sasl_sender, ", sasl_sender=", ""),
248 IFELSE(state->sasl_sender, state->sasl_sender, ""));
251 /* smtpd_sasl_mail_reset - SASL-specific MAIL FROM cleanup */
253 void smtpd_sasl_mail_reset(SMTPD_STATE *state)
255 if (state->sasl_sender) {
256 myfree(state->sasl_sender);
257 state->sasl_sender = 0;
261 /* permit_sasl_auth - OK for authenticated connection */
263 int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
265 if (state->sasl_method && strcasecmp(state->sasl_method, "anonymous"))
266 return (ifyes);
267 return (ifnot);
270 #endif