smtpd_sasl_proto.c [plain text]
#include <sys_defs.h>
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>
#include <mail_params.h>
#include <mail_proto.h>
#include <mail_error.h>
#include <ehlo_mask.h>
#include "smtpd.h"
#include "smtpd_token.h"
#include "smtpd_chat.h"
#include "smtpd_sasl_proto.h"
#include "smtpd_sasl_glue.h"
#ifdef USE_SASL_AUTH
int smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
{
char *auth_mechanism;
char *initial_response;
const char *err;
if (var_helo_required && state->helo_name == 0) {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "503 5.5.1 Error: send HELO/EHLO first");
return (-1);
}
if (SMTPD_STAND_ALONE(state) || !var_smtpd_sasl_enable
|| (state->ehlo_discard_mask & EHLO_MASK_AUTH)) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "503 5.5.1 Error: authentication not enabled");
return (-1);
}
if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0) {
if (err[0] == '5') {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "%s", err);
return (-1);
}
else if (err[0] == '4') {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "454 4.3.0 Try again later");
return (-1);
}
}
#ifdef USE_TLS
if (state->tls_auth_only && !state->tls_context) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "538 5.7.0 Encryption required for requested authentication mechanism");
return (-1);
}
#endif
if (state->sasl_username) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "503 5.5.1 Error: already authenticated");
return (-1);
}
if (argc < 2 || argc > 3) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 5.5.4 Syntax: AUTH mechanism");
return (-1);
}
auth_mechanism = argv[1].strval;
initial_response = (argc == 3 ? argv[2].strval : 0);
#ifdef __APPLE_OS_X_SERVER__
if ( var_smtpd_use_pw_server && (strcasecmp( auth_mechanism, "GSSAPI" ) != 0) )
{
err = smtpd_pw_server_authenticate(state, auth_mechanism, initial_response);
if (err != 0) {
msg_warn("%s[%s]: SASL %s authentication failed",
state->name, state->addr, auth_mechanism);
smtpd_chat_reply(state, "%s", err);
return (-1);
}
smtpd_chat_reply(state, "235 Authentication successful");
return (0);
}
else
return (smtpd_sasl_authenticate(state, auth_mechanism, initial_response));
#else
return (smtpd_sasl_authenticate(state, auth_mechanism, initial_response));
#endif
}
void smtpd_sasl_auth_reset(SMTPD_STATE *state)
{
smtpd_sasl_logout(state);
}
char *smtpd_sasl_mail_opt(SMTPD_STATE *state, const char *addr)
{
if (!var_smtpd_sasl_enable) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
return ("503 5.5.4 Error: authentication disabled");
}
#if 0
if (state->sasl_username == 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
return ("503 5.5.4 Error: send AUTH command first");
}
#endif
if (state->sasl_sender != 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
return ("503 5.5.4 Error: multiple AUTH= options");
}
if (strcmp(addr, "<>") != 0) {
state->sasl_sender = mystrdup(addr);
printable(state->sasl_sender, '?');
}
return (0);
}
void smtpd_sasl_mail_log(SMTPD_STATE *state)
{
#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
msg_info("%s: client=%s%s%s%s%s%s%s",
state->queue_id ? state->queue_id : "NOQUEUE", FORWARD_NAMADDR(state),
IFELSE(state->sasl_method, ", sasl_method=", ""),
IFELSE(state->sasl_method, state->sasl_method, ""),
IFELSE(state->sasl_username, ", sasl_username=", ""),
IFELSE(state->sasl_username, state->sasl_username, ""),
IFELSE(state->sasl_sender, ", sasl_sender=", ""),
IFELSE(state->sasl_sender, state->sasl_sender, ""));
}
void smtpd_sasl_mail_reset(SMTPD_STATE *state)
{
if (state->sasl_sender) {
myfree(state->sasl_sender);
state->sasl_sender = 0;
}
}
int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
{
if (state->sasl_method && strcasecmp(state->sasl_method, "anonymous"))
return (ifyes);
return (ifnot);
}
#endif