View | Details | Raw Unified | Return to bug 55477
Collapse All | Expand All

(-)java/org/apache/catalina/realm/LocalStrings.properties (+6 lines)
Lines 58-63 Link Here
58
jndiRealm.exception=Exception performing authentication
58
jndiRealm.exception=Exception performing authentication
59
jndiRealm.exception.retry=Exception performing authentication. Retrying...
59
jndiRealm.exception.retry=Exception performing authentication. Retrying...
60
jndiRealm.open=Exception opening directory server connection
60
jndiRealm.open=Exception opening directory server connection
61
mappingRealm.fileNotExists=Realm mapping file {0} does not exist. No security role will be available
62
mappingRealm.invalidMapping=Invalid syntax in mapping [{0}]
63
mappingRealm.loadFailed=Could not Realm mapping file {0}
64
mappingRealm.loadOK=Loaded Realm mapping file {0}
65
mappingRealm.loadRoleMappings=Load role mappings from configuration, ignore {0}
66
mappingRealm.mapped=Mapped application security role [{0}] to realm security role [{1}]
61
memoryRealm.authenticateFailure=Username {0} NOT successfully authenticated
67
memoryRealm.authenticateFailure=Username {0} NOT successfully authenticated
62
memoryRealm.authenticateSuccess=Username {0} successfully authenticated
68
memoryRealm.authenticateSuccess=Username {0} successfully authenticated
63
memoryRealm.loadExist=Memory database file {0} cannot be read
69
memoryRealm.loadExist=Memory database file {0} cannot be read
(-)java/org/apache/catalina/realm/MappingRealm.java (+306 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
package org.apache.catalina.realm;
19
20
import java.security.Principal;
21
import java.util.Properties;
22
import java.io.IOException;
23
import java.io.File;
24
import java.io.FileInputStream;
25
26
import org.apache.catalina.Globals;
27
import org.apache.catalina.Wrapper;
28
import org.apache.catalina.LifecycleException;
29
import org.apache.juli.logging.Log;
30
import org.apache.juli.logging.LogFactory;
31
32
/**
33
 * This class extends the CombinedRealm (hence it can wrap other Realms) to
34
 * map application security roles to different realm roles. This is useful
35
 * when you cannot change applications to match your internal role names.
36
 * This implementation of <b>Realm</b> reads a properties file to configure
37
 * the mapping of roles.
38
 * 
39
 * <strong>IMPLEMENTATION NOTE</strong>: It is assumed that the in-memory
40
 * collection representing our role mappings is initialized at application 
41
 * startup and never modified again. Therefore, no thread synchronization is 
42
 * performed around accesses to the mappings collection.
43
 *
44
 * @author Stefan Mayr
45
 * @version $Id$
46
 */
47
48
public class MappingRealm extends CombinedRealm {
49
50
    private static final Log log = LogFactory.getLog(MappingRealm.class);
51
52
  	
53
    // ----------------------------------------------------- Instance Variables
54
55
    /**
56
     * Internal security role translation
57
     */
58
    protected Properties mapping = null;
59
60
	/**
61
     * The pathname (absolute or relative to Catalina's current working
62
     * directory) of the properties file containing the role mapping.
63
     */
64
	protected String pathname = "conf/mapping.properties";
65
66
	/**
67
	 * Regular expression describing the symbol or string used as assignment 
68
	 * operator when using roleMappings. Defaults to "=".
69
	 */
70
	protected String assignment = "=";
71
	
72
	/**
73
     * Regular expression describing the symbol or string used as separator 
74
     * between different assignments when using roleMappings. Defaults to ";".
75
     */
76
    protected String separator = ";";
77
    
78
    /**
79
     * String with role mappings. If this is set the properties file is 
80
     * ignored. Uses the assignment and separator variables to split the
81
     * string into single role mappings.
82
     */
83
    protected String roleMappings = null;
84
    
85
    /**
86
     * Descriptive information about this Realm implementation.
87
     */
88
    protected static final String info =
89
        "org.apache.catalina.realm.MappingRealm/1.0";
90
91
    /**
92
     * Descriptive information about this Realm implementation.
93
     */
94
    protected static final String name = "MappingRealm";
95
		
96
    /**
97
     * Return descriptive information about this Realm implementation and
98
     * the corresponding version number, in the format
99
     * <code>&lt;description&gt;/&lt;version&gt;</code>.
100
     */
101
    @Override
102
    public String getInfo() {
103
104
        return info;
105
106
    }
107
108
	/**
109
     * Return a short name for this Realm implementation.
110
     */
111
    @Override
112
    protected String getName() {
113
114
        return (name);
115
116
    }
117
	
118
    /**
119
     * Get assignment string
120
     */
121
    public String getAssignment() {
122
        return assignment;
123
    }
124
    
125
    /**
126
     * Set assignment string
127
     * 
128
     * @param assignment Regular expression to split application security role
129
     *  name from the realm role name in the mapping string 
130
     */
131
    public void setAssignment(String assignment) {
132
        this.assignment=assignment;
133
    }        
134
    
135
	/**
136
     * Get pathname of mapping properties files
137
     */
138
    public String getPathname() {
139
        return pathname;
140
    }
141
142
    /**
143
     * Set the pathname of our properties file containing role mappings.
144
     * If a relative pathname is specified, it is resolved against 
145
     * "catalina.base".
146
     *
147
     * @param pathname The new pathname
148
     */
149
    public void setPathname(String pathname) {
150
        this.pathname = pathname;
151
    }
152
    
153
    /**
154
     * Get mapping rule string
155
     */
156
    public String getRoleMappings() {
157
        return roleMappings;
158
    }
159
160
    /**
161
     * Set the role mappings as string. The string is split into parts using 
162
     * the assignment and separator variables. If this string is set the 
163
     * properties file in pathname is ignored.
164
     * 
165
     * @param roleMappings String of role mappings
166
     */
167
    public void setRoleMappings(String roleMappings) {
168
        this.roleMappings=roleMappings;
169
    }
170
171
    /**
172
     * Get separator string
173
     */
174
    public String getSeparator() {
175
        return separator;
176
    }
177
178
    /**
179
     * Set separator string
180
     * 
181
     * @param separator Regular expression to split the roles in the mapping 
182
     *  string
183
     */
184
    public void setSeparator(String separator) {
185
        this.separator=separator;
186
    }
187
188
    // ---------------------------------------------------------- Realm Methods
189
190
    /**
191
     * Return <code>true</code> if the specified Principal has the specified
192
     * security role, within the context of this Realm; otherwise return
193
     * <code>false</code>.  This method can be overridden by Realm
194
     * implementations, but the default is adequate when an instance of
195
     * <code>GenericPrincipal</code> is used to represent authenticated
196
     * Principals from this Realm.
197
     *
198
     * @param principal Principal for whom the role is to be checked
199
     * @param role Security role to be checked
200
     */
201
	 @Override
202
	public boolean hasRole(Wrapper wrapper, Principal principal, String role) {
203
	
204
		// Copied from GenericPrincipal
205
		if("*".equals(role)) { // Special 2.4 role meaning everyone
206
            return true;
207
		}
208
        if (role == null) {
209
            return (false);
210
		}
211
		
212
		String mappedRole = mapping.getProperty(role);
213
		
214
		if((mappedRole != null) && super.hasRole(wrapper, principal, mappedRole)) {
215
			if (log.isDebugEnabled()) {
216
                log.debug(sm.getString("mappingRealm.mapped", role, mappedRole));
217
            }
218
			return true;
219
		} else {
220
			return false;
221
		} 
222
    }
223
	
224
	
225
	// ------------------------------------------------------ Lifecycle Methods
226
227
228
    /**
229
     * Prepare for the beginning of active use of the public methods of this
230
     * component and implement the requirements of
231
     * {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
232
     *
233
     * @exception LifecycleException if this component detects a fatal error
234
     *  that prevents this component from being used
235
     */
236
    @Override
237
    protected void startInternal() throws LifecycleException {
238
239
		mapping = new Properties();
240
241
		if (roleMappings != null) {
242
	        log.info(sm.getString("mappingRealm.loadRoleMappings",pathname));
243
		    for (String entry : roleMappings.split(separator)) {
244
		        String[] kv = entry.split(assignment, 2);
245
		        if (kv.length == 2) {
246
		            mapping.setProperty(kv[0], kv[1]);
247
		        } else {
248
		            log.error(
249
		                    sm.getString("mappingRealm.invalidMapping",entry)
250
		            );
251
		        }
252
		    }
253
		} else {
254
    		File file = new File(pathname);
255
            if (!file.isAbsolute()) {
256
                file = new File(System.getProperty(Globals.CATALINA_BASE_PROP),
257
                                pathname);
258
            }
259
            if (file.exists()) {
260
    			FileInputStream fis = null;
261
    			try {
262
    				fis =  new FileInputStream(file);
263
    				mapping.load(fis);
264
    				log.info(sm.getString("mappingRealm.loadOK", pathname));
265
    			} catch (IOException ioe) {
266
    				log.error(sm.getString("mappingRealm.loadFailed", 
267
    				                        pathname));
268
    			} finally {
269
    				 if (fis != null) {
270
    					try {
271
    						fis.close();
272
    					} catch (IOException ioe) {
273
    						// Ignore
274
    					}
275
    				}
276
    			}
277
    		} else {
278
    			log.error(sm.getString("mappingRealm.fileNotExists", 
279
    			                        pathname));
280
            }
281
		}
282
		
283
        super.startInternal();
284
    }
285
286
287
    /**
288
     * Gracefully terminate the active use of the public methods of this
289
     * component and implement the requirements of
290
     * {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
291
     *
292
     * @exception LifecycleException if this component detects a fatal error
293
     *  that needs to be reported
294
     */
295
    @Override
296
    protected void stopInternal() throws LifecycleException {
297
298
        // Perform normal superclass finalization
299
        super.stopInternal();
300
301
		// Release mappings
302
        mapping = null;
303
        roleMappings = null;
304
    }
305
}
306
(-)webapps/docs/config/realm.xml (+52 lines)
Lines 24-29 Link Here
24
24
25
  <properties>
25
  <properties>
26
    <author email="craigmcc@apache.org">Craig R. McClanahan</author>
26
    <author email="craigmcc@apache.org">Craig R. McClanahan</author>
27
    <author>Stefan Mayr</author>
27
    <title>The Realm Component</title>
28
    <title>The Realm Component</title>
28
  </properties>
29
  </properties>
29
30
Lines 979-985 Link Here
979
    using the LockOutRealm component.</p>
980
    using the LockOutRealm component.</p>
980
981
981
  </subsection>
982
  </subsection>
983
  
984
  <subsection name="Mapping Realm - org.apache.catalina.realm.MappingRealm">
985
  
986
    <p><strong>Mapping Realm</strong> is an implementation of the Tomcat
987
    <code>Realm</code> interface that extends the CombinedRealm to map 
988
    application security roles to different realm roles. This is useful
989
    when you cannot change applications to match your internal role names. 
990
    This implementation of <b>Realm</b> reads a properties file to configure
991
    the mapping of roles.</p>
982
992
993
    <p>This Realm does not require modification to the underlying Realms or the
994
    associated user storage mechanisms. It is limited to translate application
995
    security roles to realm roles using the given mappings. Roles that are not 
996
    defined in the mappings are NOT passed to sub-realms.</p>
997
998
    <p>Sub-realms are defined by nesting <code>Realm</code> elements inside the
999
    <code>Realm</code> element that defines the MappingRealm. Authentication
1000
    will be attempted against each <code>Realm</code> in the order they are
1001
    listed. Authentication against any Realm will be sufficient to authenticate
1002
    the user.</p>
1003
1004
    <p>The Mapping Realm implementation supports the following
1005
    additional attributes:</p>
1006
    
1007
  	<attributes>
1008
      <attribute name="assignment" required="false">
1009
        <p>Regular expression to split application security role name from the 
1010
        realm role name in the roleMapping string. 
1011
        If no assignment is specified, the default value is <code>=</code>.</p>
1012
      </attribute>
1013
      <attribute name="pathname" required="false">
1014
        <p>Absolute or relative (to $CATALINA_BASE) pathname to the properties 
1015
        file containing our role mappings. If no pathname is specified, the
1016
        default value is <code>conf/mapping.properties</code>.</p>
1017
      </attribute>
1018
      <attribute name="roleMappings" required="false">
1019
        <p>Inline declaration of role mappings. If this is specified the 
1020
        properties file in pathname is ignored. The string is split into 
1021
        multiple role mappings using the assignment and separator attributes.
1022
        </p>
1023
      </attribute>
1024
      <attribute name="separator" required="false">
1025
        <p>Regular expression to split the roles in the roleMapping string. 
1026
        If no separator is specified, the default value is <code>;</code>.</p>
1027
      </attribute>
1028
    </attributes>
1029
    
1030
    <p>See the <a href="../realm-howto.html">Container-Managed Security
1031
    Guide</a> for more information on setting up container managed security
1032
    using the MappingRealm component.</p>
1033
  </subsection>
1034
983
</section>
1035
</section>
984
1036
985
1037
(-)webapps/docs/realm-howto.xml (+67 lines)
Lines 26-31 Link Here
26
        <author email="craigmcc@apache.org">Craig R. McClanahan</author>
26
        <author email="craigmcc@apache.org">Craig R. McClanahan</author>
27
        <author email="yoavs@apache.org">Yoav Shapira</author>
27
        <author email="yoavs@apache.org">Yoav Shapira</author>
28
        <author email="arjaquith@mindspring.com">Andrew R. Jaquith</author>
28
        <author email="arjaquith@mindspring.com">Andrew R. Jaquith</author>
29
        <author>Stefan Mayr</author>
29
        <title>Realm Configuration HOW-TO</title>
30
        <title>Realm Configuration HOW-TO</title>
30
    </properties>
31
    </properties>
31
32
Lines 1215-1220 Link Here
1215
1216
1216
</subsection>
1217
</subsection>
1217
1218
1219
<subsection name="MappingRealm">
1220
1221
    <h3>Introduction</h3>
1222
1223
    <p><strong>Mapping Realm</strong> is an implementation of the Tomcat
1224
    <code>Realm</code> interface that extends the CombinedRealm to map 
1225
    application security roles to different realm roles. This is useful
1226
    when you cannot change applications to match your internal role names. 
1227
    This implementation of <b>Realm</b> reads a properties file to configure
1228
    the mapping of roles.</p>
1229
1230
    <p>This Realm does not require modification to the underlying Realms or the
1231
    associated user storage mechanisms. It is limited to translate application
1232
    security roles to realm roles using the given mappings. Roles that are not 
1233
    defined in the mappings are NOT passed to sub-realms.</p>
1234
1235
    <p>Sub-realms are defined by nesting <code>Realm</code> elements inside the
1236
    <code>Realm</code> element that defines the MappingRealm. Authentication
1237
    will be attempted against each <code>Realm</code> in the order they are
1238
    listed. Authentication against any Realm will be sufficient to authenticate
1239
    the user.</p>
1240
1241
    <h3>Realm Element Attributes</h3>
1242
    <p>To configure a MappingRealm, you create a <code>&lt;Realm&gt;</code>
1243
    element and nest it in your <code>$CATALINA_BASE/conf/server.xml</code>
1244
    file within your <code>&lt;Engine&gt;</code> or <code>&lt;Host&gt;</code>.
1245
    You can also nest inside a <code>&lt;Context&gt;</code> node in a
1246
    <code>context.xml</code> file. The attributes for the
1247
    MappingRealm are defined in the <a href="config/realm.html">Realm</a>
1248
    configuration documentation.</p>
1249
1250
<h3>Example using mapping.properties</h3>
1251
1252
<p>Here is an example of how your server.xml snippet should look to add mapping
1253
functionality to a UserDatabase Realm.</p>
1254
1255
<source>
1256
&lt;Realm className="org.apache.catalina.realm.MappingRealm" &gt;
1257
   &lt;Realm className="org.apache.catalina.realm.UserDatabaseRealm"
1258
             resourceName="UserDatabase"/&gt;
1259
&lt;/Realm&gt;
1260
</source>
1261
1262
<p>Here is an example of how your <code>conf/mapping.properties</code> snippet 
1263
should look to add map the manager-gui role from Tomcat Manager to the example 
1264
tomcat role in the default UserDatabase Realm configuration in 
1265
<code>conf/tomcat-users.xml</code>.</p>
1266
1267
<source>
1268
manager-gui=tomcat
1269
</source>
1270
1271
<h3>Example using inline configuration</h3>
1272
1273
<p>Here is an example of how your server.xml snippet should look if you use 
1274
inline configuration and ignore the properties file</p>
1275
1276
<source>
1277
&lt;Realm className="org.apache.catalina.realm.MappingRealm" roleMappings="manager-gui=tomcat"&gt;
1278
   &lt;Realm className="org.apache.catalina.realm.UserDatabaseRealm"
1279
             resourceName="UserDatabase"/&gt;
1280
&lt;/Realm&gt;
1281
</source>
1282
1283
</subsection>
1284
1218
</section>
1285
</section>
1219
1286
1220
</body>
1287
</body>

Return to bug 55477