1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.security;
35
36 import info.magnolia.jcr.node2bean.Node2BeanTransformer;
37 import info.magnolia.jcr.node2bean.PropertyTypeDescriptor;
38 import info.magnolia.jcr.node2bean.TransformationState;
39 import info.magnolia.jcr.node2bean.TypeDescriptor;
40 import info.magnolia.jcr.node2bean.TypeMapping;
41 import info.magnolia.jcr.node2bean.impl.Node2BeanTransformerImpl;
42 import info.magnolia.objectfactory.ComponentProvider;
43 import info.magnolia.objectfactory.ObservedComponentFactory;
44 import info.magnolia.repository.RepositoryConstants;
45 import org.apache.commons.net.util.SubnetUtils;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import java.util.Arrays;
50 import java.util.Collections;
51 import java.util.HashMap;
52 import java.util.Map;
53 import java.util.Set;
54 import java.util.TreeSet;
55
56 import javax.jcr.RepositoryException;
57 import javax.servlet.http.HttpServletRequest;
58
59
60
61
62
63
64 public class IPSecurityManagerImpl implements IPSecurityManager {
65
66 private static final Logger log = LoggerFactory.getLogger(IPSecurityManagerImpl.class);
67 private static final String ALL = "*";
68
69
70
71
72 private Map<String, Rule> rules;
73
74 public IPSecurityManagerImpl() {
75 this.rules = new HashMap<String, Rule>();
76 }
77
78 @Override
79 public boolean isAllowed(HttpServletRequest req) {
80 final Rule rule = getRule(req.getRemoteAddr());
81 return rule != null && rule.allowsMethod(req.getMethod());
82 }
83
84 @Override
85 public boolean isAllowed(String ip) {
86 return getRule(ip) != null;
87 }
88
89 protected Rule getRule(String ip) {
90 final Map<String, Rule> rules = getRules();
91
92
93 if (rules.containsKey(ip)) {
94 return rules.get(ip);
95 }
96
97
98 for (Map.Entry<String, Rule> entry : rules.entrySet()) {
99 final String ruleIp = entry.getKey();
100
101 if (ruleIp.contains("/")) {
102
103 try {
104 if (new SubnetUtils(ruleIp).getInfo().isInRange(ip)) {
105
106 return entry.getValue();
107 }
108 } catch (IllegalArgumentException e) {
109 log.warn("Cannot parse IP address: {}", ip);
110 }
111 }
112 }
113
114
115 return (rules.containsKey(ip)) ? rules.get(ip) : rules.get(ALL);
116 }
117
118 public Map<String, Rule> getRules() {
119 return rules;
120 }
121
122 public void setRules(Map<String, Rule> rules) {
123 this.rules = rules;
124 }
125
126 public void addRule(String name, Rule rule) {
127 rules.put(name, rule);
128 }
129
130
131
132
133 public static final class InstanceFactory extends ObservedComponentFactory<IPSecurityManager> {
134 public InstanceFactory() {
135 super(RepositoryConstants.CONFIG, "/server/IPConfig", IPSecurityManager.class);
136 }
137
138 @Override
139 protected Node2BeanTransformer getNode2BeanTransformer() {
140 return new IPSecurityManagerTransformer();
141 }
142 }
143
144
145
146
147 public static final class IPSecurityManagerTransformer extends Node2BeanTransformerImpl {
148
149 @Override
150 public void setProperty(TypeMapping typeMapping, TransformationState state, PropertyTypeDescriptor descriptor, Map<String, Object> values) throws RepositoryException {
151 final Object currentBean = state.getCurrentBean();
152 if (currentBean instanceof IPSecurityManagerImpl) {
153 final IPSecurityManagerImplmagnolia/cms/security/IPSecurityManagerImpl.html#IPSecurityManagerImpl">IPSecurityManagerImpl ipSecMan = (IPSecurityManagerImpl) currentBean;
154 for (Object o : values.values()) {
155 if (o instanceof Rule) {
156 final Rule rule = (Rule) o;
157 ipSecMan.addRule(rule.getIP(), rule);
158 }
159 }
160 }
161 super.setProperty(typeMapping, state, descriptor, values);
162 }
163
164 @Override
165 protected TypeDescriptorDescriptor">TypeDescriptor onResolveType(TypeMapping typeMapping, TransformationState state, TypeDescriptor resolvedType, ComponentProvider componentProvider) {
166 if (state.getLevel() == 2 && resolvedType == null) {
167 return typeMapping.getTypeDescriptor(Rule.class);
168 }
169 return super.onResolveType(typeMapping, state, resolvedType, componentProvider);
170 }
171
172 }
173
174
175
176
177 public static final class Rule {
178 private String name;
179 private String ip;
180 private Set<String> methods;
181
182 public Rule() {
183 this.methods = Collections.emptySet();
184 }
185
186 public String getName() {
187 return name;
188 }
189
190 public void setName(String name) {
191 this.name = name;
192 }
193
194 public String getIP() {
195 return ip;
196 }
197
198 public void setIP(String ip) {
199 this.ip = ip;
200 }
201
202 public boolean allowsMethod(String s) {
203 return methods.contains(s);
204 }
205
206 public String getMethods() {
207 throw new IllegalStateException("Just faking a getter for content2bean's sake.");
208 }
209
210 public void setMethods(String methods) {
211 this.methods = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
212 this.methods.addAll(Arrays.asList(methods.split(",")));
213 }
214 }
215
216 }