DefaultAuthorizationPolicy.java 7.58 KB
Newer Older
1 2 3 4 5
/**
 * $RCSfile$
 * $Revision: $
 * $Date: 2006-04-20 10:46:24 -0500 (Thu, 20 Apr 2006) $
 *
6
 * Copyright (C) 2004-2008 Jive Software. All rights reserved.
7
 *
8 9 10 11 12 13 14 15 16 17 18
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
19 20 21 22 23
 */

package org.jivesoftware.openfire.auth;

import java.util.StringTokenizer;
24
import java.util.Vector;
25

26
import org.jivesoftware.openfire.admin.AdminManager;
27 28 29 30
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/**
 * Different clients perform authentication differently, so this policy 
 * will authorize any principal to a requested user that match specific 
 * conditions that are considered secure defaults for most installations. 
 *
 * Keep in mind if a client does not request any username Java copies the
 * authenticated ID to the requested username.
 *
 * <ul>
 * <li>If the authenticated ID is in the form of a plain username, and the 
 *     requested user is in the form of a plain username, then the two must
 *     be exactly the same.  
 * <li>If the authenticated ID contains an '@', then the portion before the 
 *     '@' must match exactly the requested username and the portion after 
 *     the '@' must match at least one of the following:
 *     <ul>
 *     <li>The XMPP domain of the server
 *     <li>The SASL realm of the server
 *     <li>Be in the list of acceptable realms
 *     </ul>
51
 * <li>If the requested username contains an '@' then the portion before the
52 53 54 55 56 57 58 59 60 61 62
 *     '@' will be considered the requested username only if the portion after
 *     the '@' matches the XMPP domain of the server or the portion after the 
 *     '@' in the authenticated ID, if any.
 * </ul>
 *
 * 
 * @see AuthorizationManager
 * @author Jay Kline
 */
public class DefaultAuthorizationPolicy implements AuthorizationPolicy {

63 64
	private static final Logger Log = LoggerFactory.getLogger(DefaultAuthorizationPolicy.class);

65
    private Vector<String> approvedRealms;
66
    private boolean proxyAuth;
67 68

    public DefaultAuthorizationPolicy() {
69
        approvedRealms = new Vector<>();
70
        proxyAuth = false;
71
        
72
        String realmList = JiveGlobals.getProperty("sasl.approvedRealms");
73 74 75 76 77 78
        if(realmList != null) {
            StringTokenizer st = new StringTokenizer(realmList, " ,\t\n\r\f");
            while(st.hasMoreTokens()) {
                approvedRealms.add(st.nextToken());
            }
        }
79
        proxyAuth = JiveGlobals.getBooleanProperty("sasl.proxyAuth", false);
80 81 82
    }

    /**
guus's avatar
guus committed
83
     * Returns true if the principal is explicitly authorized to the JID
84 85
     *
     * @param username  The username requested.
86
     * @param authenID The authenticated ID (principal) requesting the username.
87 88
     * @return true if the authenticated ID is authorized to the requested user.
     */
89
    @Override
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    public boolean authorize(String username, String authenID) {
        boolean authorized = false;

        String userUser = username; //I know, I know, dumb variable name...
        String userRealm = null;
 
        String authenUser = authenID;
        String authenRealm = null;

        if(username.contains("@")) {
            userUser = username.substring(0,username.lastIndexOf("@"));
            userRealm = username.substring((username.lastIndexOf("@")+1)); 
        }
        if(authenID.contains("@")){
            authenUser = authenID.substring(0,(authenID.lastIndexOf("@")));
            authenRealm = authenID.substring((authenID.lastIndexOf("@")+1));
        }

108 109 110 111 112 113 114 115 116
        if (!proxyAuth || !AdminManager.getInstance().isUserAdmin(authenUser, true)) {
            if(!userUser.equals(authenUser)) {
                //for this policy the user portion of both must match, so lets short circut here if we can
                if(JiveGlobals.getBooleanProperty("xmpp.auth.ignorecase",true)) {
                    if(!userUser.toLowerCase().equals(authenUser.toLowerCase())){
                        if (Log.isDebugEnabled()) {
                            Log.debug("DefaultAuthorizationPolicy: usernames don't match ("+userUser+" "+authenUser+")");
                        }
                        return false;
117
                    }
118 119
                } else {
                    Log.debug("DefaultAuthorizationPolicy: usernames don't match ("+userUser+" "+authenUser+")");
120 121 122 123 124 125 126 127 128 129
                    return false;
                }
            }
        }
        Log.debug("DefaultAuthorizationPolicy: Checking authenID realm");
        // Next up, check if the authenID realm is acceptable. 
        if(authenRealm != null) {
            if(authenRealm.equals(JiveGlobals.getProperty("xmpp.domain")))  {
                Log.debug("DefaultAuthorizationPolicy: authenRealm = xmpp.domain");
                authorized = true;
130
            } else if(authenRealm.equals(JiveGlobals.getProperty("sasl.realm")))  {
131 132 133 134 135
                Log.debug("DefaultAuthorizationPolicy: authenRealm = sasl.realm");
                authorized = true;
            } else { 
                for(String realm : approvedRealms) {
                    if(authenRealm.equals(realm)) {
136 137 138
                        if (Log.isDebugEnabled()) {
                            Log.debug("DefaultAuthorizationPolicy: authenRealm = "+realm+" which is approved");
                        }
139 140
                        authorized = true;
                    } else {
141 142 143
                        if (Log.isDebugEnabled()) {
                            Log.debug("DefaultAuthorizationPolicy: authenRealm != "+realm+" which is approved");
                        }
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
                    }
                }
            }
        } else {
            //no realm in the authenID
            authorized = true;
        }

        if(!authorized) {
            return false;
        }  else {
            //reset for next round of tests
            authorized = false;
        }
        //Next up, check if the username realm is acceptable.
        if(userRealm != null) {
            if(userRealm.equals(JiveGlobals.getProperty("xmpp.domain"))) {
                Log.debug("DefaultAuthorizationPolicy: userRealm = xmpp.domain");
                authorized = true;
            } else {
                if(authenRealm != null && authenRealm.equals(userRealm)) {
                    //authen and username are identical
166 167 168
                    if (Log.isDebugEnabled()) {
                        Log.debug("DefaultAuthorizationPolicy: userRealm = "+authenRealm+" which is approved");
                    }
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
                    authorized = true;
                }
            }
        } else {
            authorized = true;
        }

        //no more checks
        return authorized;
    }

    /**
     * Returns the short name of the Policy
     *
     * @return The short name of the Policy
     */
185
    @Override
186 187 188 189 190 191 192 193 194
    public String name() {
        return "Default Policy";
    }

    /**
     * Returns a description of the Policy
     *
     * @return The description of the Policy.
     */
195
    @Override
196 197 198 199 200 201 202
    public String description() {
        return "Different clients perform authentication differently, so this policy "+ 
               "will authorize any principal to a requested user that match specific "+
               "conditions that are considered secure defaults for most installations.";
    }
}