001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019 package org.apache.james.protocols.smtp.core;
020
021 import java.util.Locale;
022
023 import org.apache.james.protocols.smtp.SMTPRetCode;
024 import org.apache.james.protocols.smtp.SMTPSession;
025 import org.apache.james.protocols.smtp.dsn.DSNStatus;
026 import org.apache.james.protocols.smtp.hook.HookResult;
027 import org.apache.james.protocols.smtp.hook.HookReturnCode;
028 import org.apache.james.protocols.smtp.hook.RcptHook;
029 import org.apache.mailet.MailAddress;
030
031 /**
032 * Handler which check if the authenticated user is the same as the one used as MAIL FROM
033 */
034 public abstract class AbstractSenderAuthIdentifyVerificationRcptHook implements RcptHook {
035 /**
036 * @see org.apache.james.protocols.smtp.hook.RcptHook#doRcpt(org.apache.james.protocols.smtp.SMTPSession,
037 * org.apache.mailet.MailAddress, org.apache.mailet.MailAddress)
038 */
039 public HookResult doRcpt(SMTPSession session, MailAddress sender,
040 MailAddress rcpt) {
041 if (session.getUser() != null) {
042 String authUser = (session.getUser()).toLowerCase(Locale.US);
043 MailAddress senderAddress = (MailAddress) session.getState().get(
044 SMTPSession.SENDER);
045 String username= null;
046
047 if (senderAddress != null) {
048 if (useVirtualHosting()) {
049 username = senderAddress.toString();
050 } else {
051 username = senderAddress.getLocalPart();
052 }
053 }
054
055 // Check if the sender address is the same as the user which was used to authenticate.
056 // Its important to ignore case here to fix JAMES-837. This is save todo because if the handler is called
057 // the user was already authenticated
058 if ((senderAddress == null)
059 || (!authUser.equalsIgnoreCase(username))
060 || (!isLocalDomain(senderAddress.getDomain()))) {
061 return new HookResult(HookReturnCode.DENY,
062 SMTPRetCode.BAD_SEQUENCE,
063 DSNStatus.getStatus(DSNStatus.PERMANENT,
064 DSNStatus.SECURITY_AUTH)
065 + " Incorrect Authentication for Specified Email Address");
066 }
067 }
068 return new HookResult(HookReturnCode.DECLINED);
069 }
070
071
072 /**
073 * Return true if the given domain is a local domain for this server
074 *
075 * @param domain
076 * @return isLocal
077 */
078 protected abstract boolean isLocalDomain(String domain);
079
080 /**
081 * Return true if virtualHosting should get used. If so the full email address will get used to
082 * match against the supplied auth username
083 *
084 * @return useVirtualHosting
085 */
086 protected abstract boolean useVirtualHosting();
087
088 }