001
014
015 package com.liferay.portal.kernel.log;
016
017 import com.liferay.portal.kernel.util.CharPool;
018 import com.liferay.portal.kernel.util.GetterUtil;
019 import com.liferay.portal.kernel.util.PropsKeys;
020 import com.liferay.portal.kernel.util.StringUtil;
021 import com.liferay.portal.kernel.util.SystemProperties;
022
023 import java.util.ArrayList;
024 import java.util.List;
025
026
030 public class SanitizerLogWrapper extends LogWrapper {
031
032 public static Log allowCRLF(Log log) {
033 if (!(log instanceof SanitizerLogWrapper)) {
034 return log;
035 }
036
037 SanitizerLogWrapper sanitizerLogWrapper = (SanitizerLogWrapper)log;
038
039 sanitizerLogWrapper = new SanitizerLogWrapper(
040 sanitizerLogWrapper.getWrappedLog());
041
042 sanitizerLogWrapper._allowCRLF = true;
043
044 return sanitizerLogWrapper;
045 }
046
047 public static void init() {
048 if (!_LOG_SANITIZER_ENABLED) {
049 return;
050 }
051
052 _LOG_SANITIZER_ESCAPE_HTML_ENABLED = GetterUtil.getBoolean(
053 SystemProperties.get(PropsKeys.LOG_SANITIZER_ESCAPE_HTML_ENABLED));
054
055 _LOG_SANITIZER_REPLACEMENT_CHARACTER = (char)GetterUtil.getInteger(
056 SystemProperties.get(
057 PropsKeys.LOG_SANITIZER_REPLACEMENT_CHARACTER));
058
059 for (int i = 0; i < _whitelistCharacters.length; i++) {
060 _whitelistCharacters[i] = 1;
061 }
062
063 int[] whitelistCharacters = GetterUtil.getIntegerValues(
064 StringUtil.split(
065 SystemProperties.get(
066 PropsKeys.LOG_SANITIZER_WHITELIST_CHARACTERS)));
067
068 for (int whitelistCharacter : whitelistCharacters) {
069 if ((whitelistCharacter >= 0) &&
070 (whitelistCharacter < _whitelistCharacters.length)) {
071
072 _whitelistCharacters[whitelistCharacter] = 0;
073 }
074 else {
075 System.err.println(
076 "Unable to register log whitelist character " +
077 whitelistCharacter);
078 }
079 }
080 }
081
082 public static boolean isEnabled() {
083 return _LOG_SANITIZER_ENABLED;
084 }
085
086 public SanitizerLogWrapper(Log log) {
087 super(log);
088
089 setLogWrapperClassName(SanitizerLogWrapper.class.getName());
090 }
091
092 @Override
093 public void debug(Object msg) {
094 super.debug(sanitize(msg));
095 }
096
097 @Override
098 public void debug(Object msg, Throwable t) {
099 super.debug(sanitize(msg), sanitize(t));
100 }
101
102 @Override
103 public void debug(Throwable t) {
104 super.debug(sanitize(t));
105 }
106
107 @Override
108 public void error(Object msg) {
109 super.error(sanitize(msg));
110 }
111
112 @Override
113 public void error(Object msg, Throwable t) {
114 super.error(sanitize(msg), sanitize(t));
115 }
116
117 @Override
118 public void error(Throwable t) {
119 super.error(sanitize(t));
120 }
121
122 @Override
123 public void fatal(Object msg) {
124 super.fatal(sanitize(msg));
125 }
126
127 @Override
128 public void fatal(Object msg, Throwable t) {
129 super.fatal(sanitize(msg), sanitize(t));
130 }
131
132 @Override
133 public void fatal(Throwable t) {
134 super.fatal(sanitize(t));
135 }
136
137 @Override
138 public void info(Object msg) {
139 super.info(sanitize(msg));
140 }
141
142 @Override
143 public void info(Object msg, Throwable t) {
144 super.info(sanitize(msg), sanitize(t));
145 }
146
147 @Override
148 public void info(Throwable t) {
149 super.info(sanitize(t));
150 }
151
152 @Override
153 public void trace(Object msg) {
154 super.trace(sanitize(msg));
155 }
156
157 @Override
158 public void trace(Object msg, Throwable t) {
159 super.trace(sanitize(msg), sanitize(t));
160 }
161
162 @Override
163 public void trace(Throwable t) {
164 super.trace(sanitize(t));
165 }
166
167 @Override
168 public void warn(Object msg) {
169 super.warn(sanitize(msg));
170 }
171
172 @Override
173 public void warn(Object msg, Throwable t) {
174 super.warn(sanitize(msg), sanitize(t));
175 }
176
177 @Override
178 public void warn(Throwable t) {
179 super.warn(sanitize(t));
180 }
181
182 protected String sanitize(Object obj) {
183 if (obj == null) {
184 return null;
185 }
186
187 String message = obj.toString();
188
189 return sanitize(message, message);
190 }
191
192 protected String sanitize(String message, String defaultResult) {
193 if (message == null) {
194 return null;
195 }
196
197 char[] chars = message.toCharArray();
198 boolean hasCRLF = false;
199 boolean hasLessThanCharacter = false;
200 boolean sanitized = false;
201
202 for (int i = 0; i < chars.length; i++) {
203 int c = chars[i];
204
205 if (_allowCRLF &&
206 ((c == CharPool.NEW_LINE) || (c == CharPool.RETURN))) {
207
208 hasCRLF = true;
209
210 continue;
211 }
212
213 if ((c >= 0) && (c < _whitelistCharacters.length) &&
214 (_whitelistCharacters[c] != 0)) {
215
216 chars[i] = _LOG_SANITIZER_REPLACEMENT_CHARACTER;
217 sanitized = true;
218 }
219
220 if (c == CharPool.LESS_THAN) {
221 hasLessThanCharacter = true;
222 }
223 }
224
225 boolean escapeHTML = false;
226
227 if (_LOG_SANITIZER_ESCAPE_HTML_ENABLED && hasLessThanCharacter) {
228 escapeHTML = true;
229 }
230
231 if (sanitized || escapeHTML || hasCRLF) {
232 String sanitizedMessage = new String(chars);
233
234 if (escapeHTML) {
235 sanitizedMessage = StringUtil.replace(
236 sanitizedMessage, CharPool.LESS_THAN, _LESS_THAN_ESCAPED);
237 }
238
239 if (sanitized) {
240 sanitizedMessage = sanitizedMessage.concat(_SANITIZED);
241 }
242
243 if (hasCRLF) {
244 sanitizedMessage = CRLF_WARNING.concat(sanitizedMessage);
245 }
246
247 return sanitizedMessage;
248 }
249
250 return defaultResult;
251 }
252
253 protected Throwable sanitize(Throwable throwable) {
254 List<Throwable> throwables = new ArrayList<>();
255
256 Throwable tempThrowable = throwable;
257
258 while (tempThrowable != null) {
259 throwables.add(tempThrowable);
260
261 tempThrowable = tempThrowable.getCause();
262 }
263
264 Throwable resultThrowable = null;
265
266 boolean sanitized = false;
267
268 for (int i = throwables.size() - 1; i > - 1; i--) {
269 Throwable curThrowable = throwables.get(i);
270
271 String message = curThrowable.toString();
272
273 String sanitizedMessage = sanitize(message, null);
274
275 if (!sanitized && (sanitizedMessage == null)) {
276 resultThrowable = curThrowable;
277
278 continue;
279 }
280
281 if (sanitizedMessage == null) {
282 sanitizedMessage = message;
283 }
284
285 sanitized = true;
286
287 resultThrowable = new LogSanitizerException(
288 sanitizedMessage, curThrowable.getStackTrace(),
289 resultThrowable);
290 }
291
292 return resultThrowable;
293 }
294
295 protected static final String CRLF_WARNING =
296 "SanitizerLogWrapper warning: Following message contains CRLF " +
297 "characters\n";
298
299 private static final String _LESS_THAN_ESCAPED = "<";
300
301 private static final boolean _LOG_SANITIZER_ENABLED = GetterUtil.getBoolean(
302 SystemProperties.get(PropsKeys.LOG_SANITIZER_ENABLED));
303
304 private static boolean _LOG_SANITIZER_ESCAPE_HTML_ENABLED;
305
306 private static char _LOG_SANITIZER_REPLACEMENT_CHARACTER =
307 CharPool.UNDERLINE;
308
309 private static final String _SANITIZED = " [Sanitized]";
310
311 private static final int[] _whitelistCharacters = new int[128];
312
313 private boolean _allowCRLF;
314
315 }