1 /* $NetBSD: smtp_sasl_proto.c,v 1.3 2022/10/08 16:12:49 christos Exp $ */
2
3 /*++
4 /* NAME
5 /* smtp_sasl_proto 3
6 /* SUMMARY
7 /* Postfix SASL interface for SMTP client
8 /* SYNOPSIS
9 /* #include smtp_sasl.h
10 /*
11 /* void smtp_sasl_helo_auth(state, words)
12 /* SMTP_STATE *state;
13 /* const char *words;
14 /*
15 /* int smtp_sasl_helo_login(state)
16 /* SMTP_STATE *state;
17 /* DESCRIPTION
18 /* This module contains random chunks of code that implement
19 /* the SMTP protocol interface for SASL negotiation. The goal
20 /* is to reduce clutter in the main SMTP client source code.
21 /*
22 /* smtp_sasl_helo_auth() processes the AUTH option in the
23 /* SMTP server's EHLO response.
24 /*
25 /* smtp_sasl_helo_login() authenticates the SMTP client to the
26 /* SMTP server, using the authentication mechanism information
27 /* given by the server. The result is a Postfix delivery status
28 /* code in case of trouble.
29 /*
30 /* Arguments:
31 /* .IP state
32 /* Session context.
33 /* .IP words
34 /* List of SASL authentication mechanisms (separated by blanks)
35 /* DIAGNOSTICS
36 /* All errors are fatal.
37 /* LICENSE
38 /* .ad
39 /* .fi
40 /* The Secure Mailer license must be distributed with this software.
41 /* AUTHOR(S)
42 /* Original author:
43 /* Till Franke
44 /* SuSE Rhein/Main AG
45 /* 65760 Eschborn, Germany
46 /*
47 /* Adopted by:
48 /* Wietse Venema
49 /* IBM T.J. Watson Research
50 /* P.O. Box 704
51 /* Yorktown Heights, NY 10598, USA
52 /*
53 /* Wietse Venema
54 /* Google, Inc.
55 /* 111 8th Avenue
56 /* New York, NY 10011, USA
57 /*--*/
58
59 /* System library. */
60
61 #include <sys_defs.h>
62 #include <string.h>
63 #ifdef STRCASECMP_IN_STRINGS_H
64 #include <strings.h>
65 #endif
66
67 /* Utility library. */
68
69 #include <msg.h>
70 #include <mymalloc.h>
71 #include <stringops.h>
72
73 /* Global library. */
74
75 #include <mail_params.h>
76 #include <sasl_mech_filter.h>
77
78 /* Application-specific. */
79
80 #include "smtp.h"
81 #include "smtp_sasl.h"
82
83 #ifdef USE_SASL_AUTH
84
85 /* smtp_sasl_helo_auth - handle AUTH option in EHLO reply */
86
smtp_sasl_helo_auth(SMTP_SESSION * session,const char * words)87 void smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words)
88 {
89 const char *mech_list = sasl_mech_filter(smtp_sasl_mechs, words);
90 char *junk;
91
92 /*
93 * XXX If the server offers no compatible authentication mechanisms, then
94 * pretend that the server doesn't support SASL authentication.
95 *
96 * XXX If the server offers multiple different lists, concatenate them. Let
97 * the SASL library worry about duplicates.
98 */
99 if (session->sasl_mechanism_list) {
100 if (strcasecmp(session->sasl_mechanism_list, mech_list) != 0
101 && strlen(mech_list) > 0
102 && strlen(session->sasl_mechanism_list) < var_line_limit) {
103 junk = concatenate(session->sasl_mechanism_list, " ", mech_list,
104 (char *) 0);
105 myfree(session->sasl_mechanism_list);
106 session->sasl_mechanism_list = junk;
107 }
108 return;
109 }
110 if (strlen(mech_list) > 0) {
111 session->sasl_mechanism_list = mystrdup(mech_list);
112 } else {
113 msg_warn(*words ? "%s offered no supported AUTH mechanisms: '%s'" :
114 "%s offered null AUTH mechanism list%s",
115 session->namaddrport, words);
116 }
117 session->features |= SMTP_FEATURE_AUTH;
118 }
119
120 /* smtp_sasl_helo_login - perform SASL login */
121
smtp_sasl_helo_login(SMTP_STATE * state)122 int smtp_sasl_helo_login(SMTP_STATE *state)
123 {
124 SMTP_SESSION *session = state->session;
125 DSN_BUF *why = state->why;
126 int ret;
127
128 /*
129 * Skip authentication when no authentication info exists for this
130 * server, so that we talk to each other like strangers.
131 */
132 if (smtp_sasl_passwd_lookup(session) == 0) {
133 session->features &= ~SMTP_FEATURE_AUTH;
134 return 0;
135 }
136
137 /*
138 * Otherwise, if authentication information exists, assume that
139 * authentication is required, and assume that an authentication error is
140 * recoverable from the message delivery point of view. An authentication
141 * error is unrecoverable from a session point of view - the session will
142 * not be reused.
143 */
144 ret = 0;
145 if (session->sasl_mechanism_list == 0) {
146 dsb_simple(why, "4.7.0", "SASL authentication failed: "
147 "server %s offered no compatible authentication mechanisms for this type of connection security",
148 session->namaddr);
149 ret = smtp_sess_fail(state);
150 /* Session reuse is disabled. */
151 } else {
152 #ifndef USE_TLS
153 smtp_sasl_start(session, VAR_LMTP_SMTP(SASL_OPTS), var_smtp_sasl_opts);
154 #else
155 if (session->tls_context == 0)
156 smtp_sasl_start(session, VAR_LMTP_SMTP(SASL_OPTS),
157 var_smtp_sasl_opts);
158 else if (TLS_CERT_IS_MATCHED(session->tls_context))
159 smtp_sasl_start(session, VAR_LMTP_SMTP(SASL_TLSV_OPTS),
160 var_smtp_sasl_tlsv_opts);
161 else
162 smtp_sasl_start(session, VAR_LMTP_SMTP(SASL_TLS_OPTS),
163 var_smtp_sasl_tls_opts);
164 #endif
165 if (smtp_sasl_authenticate(session, why) <= 0) {
166 ret = smtp_sess_fail(state);
167 /* Session reuse is disabled. */
168 }
169 }
170 return (ret);
171 }
172
173 #endif
174