Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / smtp / smtp_sasl_proto.c
blob741bd61a266a55b34809b2b761743a297c5d75dd
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* smtp_sasl_proto 3
6 /* SUMMARY
7 /* Postfix SASL interface for SMTP client
8 /* SYNOPSIS
9 /* #include smtp_sasl.h
11 /* void smtp_sasl_helo_auth(state, words)
12 /* SMTP_STATE *state;
13 /* const char *words;
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.
22 /* smtp_sasl_helo_auth() processes the AUTH option in the
23 /* SMTP server's EHLO response.
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.
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
47 /* Adopted by:
48 /* Wietse Venema
49 /* IBM T.J. Watson Research
50 /* P.O. Box 704
51 /* Yorktown Heights, NY 10598, USA
52 /*--*/
54 /* System library. */
56 #include <sys_defs.h>
57 #include <string.h>
58 #ifdef STRCASECMP_IN_STRINGS_H
59 #include <strings.h>
60 #endif
62 /* Utility library. */
64 #include <msg.h>
65 #include <mymalloc.h>
66 #include <stringops.h>
68 /* Global library. */
70 #include <mail_params.h>
72 /* Application-specific. */
74 #include "smtp.h"
75 #include "smtp_sasl.h"
77 #ifdef USE_SASL_AUTH
79 /* smtp_sasl_compat_mechs - Trim server's mechanism list */
81 static const char *smtp_sasl_compat_mechs(const char *words)
83 static VSTRING *buf;
84 char *mech_list;
85 char *save_mech;
86 char *mech;
89 * Use server's mechanisms if no filter specified
91 if (smtp_sasl_mechs == 0 || *words == 0)
92 return (words);
94 if (buf == 0)
95 buf = vstring_alloc(10);
97 VSTRING_RESET(buf);
98 VSTRING_TERMINATE(buf);
100 save_mech = mech_list = mystrdup(words);
102 while ((mech = mystrtok(&mech_list, " \t")) != 0) {
103 if (string_list_match(smtp_sasl_mechs, mech)) {
104 if (VSTRING_LEN(buf) > 0)
105 VSTRING_ADDCH(buf, ' ');
106 vstring_strcat(buf, mech);
109 myfree(save_mech);
111 return (vstring_str(buf));
114 /* smtp_sasl_helo_auth - handle AUTH option in EHLO reply */
116 void smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words)
118 const char *mech_list = smtp_sasl_compat_mechs(words);
119 char *junk;
122 * XXX If the server offers no compatible authentication mechanisms, then
123 * pretend that the server doesn't support SASL authentication.
125 * XXX If the server offers multiple different lists, concatenate them. Let
126 * the SASL library worry about duplicates.
128 if (session->sasl_mechanism_list) {
129 if (strcasecmp(session->sasl_mechanism_list, mech_list) != 0
130 && strlen(mech_list) > 0
131 && strlen(session->sasl_mechanism_list) < var_line_limit) {
132 junk = concatenate(session->sasl_mechanism_list, " ", mech_list,
133 (char *) 0);
134 myfree(session->sasl_mechanism_list);
135 session->sasl_mechanism_list = junk;
137 return;
139 if (strlen(mech_list) > 0) {
140 session->sasl_mechanism_list = mystrdup(mech_list);
141 } else {
142 msg_warn(*words ? "%s offered no supported AUTH mechanisms: '%s'" :
143 "%s offered null AUTH mechanism list",
144 session->namaddrport, words);
146 session->features |= SMTP_FEATURE_AUTH;
149 /* smtp_sasl_helo_login - perform SASL login */
151 int smtp_sasl_helo_login(SMTP_STATE *state)
153 SMTP_SESSION *session = state->session;
154 DSN_BUF *why = state->why;
155 int ret;
158 * Skip authentication when no authentication info exists for this
159 * server, so that we talk to each other like strangers.
161 if (smtp_sasl_passwd_lookup(session) == 0) {
162 session->features &= ~SMTP_FEATURE_AUTH;
163 return 0;
167 * Otherwise, if authentication information exists, assume that
168 * authentication is required, and assume that an authentication error is
169 * recoverable from the message delivery point of view. An authentication
170 * error is unrecoverable from a session point of view - the session will
171 * not be reused.
173 ret = 0;
174 if (session->sasl_mechanism_list == 0) {
175 dsb_simple(why, "4.7.0", "SASL authentication failed: "
176 "server %s offered no compatible authentication mechanisms for this type of connection security",
177 session->namaddr);
178 ret = smtp_sess_fail(state);
179 /* Session reuse is disabled. */
180 } else {
181 #ifndef USE_TLS
182 smtp_sasl_start(session, VAR_SMTP_SASL_OPTS,
183 var_smtp_sasl_opts);
184 #else
185 if (session->tls_context == 0)
186 smtp_sasl_start(session, VAR_SMTP_SASL_OPTS,
187 var_smtp_sasl_opts);
188 else if (TLS_CERT_IS_MATCHED(session->tls_context))
189 smtp_sasl_start(session, VAR_SMTP_SASL_TLSV_OPTS,
190 var_smtp_sasl_tlsv_opts);
191 else
192 smtp_sasl_start(session, VAR_SMTP_SASL_TLS_OPTS,
193 var_smtp_sasl_tls_opts);
194 #endif
195 if (smtp_sasl_authenticate(session, why) <= 0) {
196 ret = smtp_sess_fail(state);
197 /* Session reuse is disabled. */
200 return (ret);
203 #endif