Merged #164 "Sanitize page parameters for XSS vulerabilities"
3 files added
33 files modified
| | |
| | | <classpathentry kind="lib" path="ext/commons-pool2-2.0.jar" sourcepath="ext/src/commons-pool2-2.0.jar" /> |
| | | <classpathentry kind="lib" path="ext/pf4j-0.8.0.jar" sourcepath="ext/src/pf4j-0.8.0.jar" /> |
| | | <classpathentry kind="lib" path="ext/tika-core-1.5.jar" sourcepath="ext/src/tika-core-1.5.jar" /> |
| | | <classpathentry kind="lib" path="ext/jsoup-1.7.3.jar" sourcepath="ext/src/jsoup-1.7.3.jar" /> |
| | | <classpathentry kind="lib" path="ext/junit-4.11.jar" sourcepath="ext/src/junit-4.11.jar" /> |
| | | <classpathentry kind="lib" path="ext/hamcrest-core-1.3.jar" sourcepath="ext/src/hamcrest-core-1.3.jar" /> |
| | | <classpathentry kind="lib" path="ext/selenium-java-2.28.0.jar" sourcepath="ext/src/selenium-java-2.28.0.jar" /> |
| | |
| | | - compile 'redis.clients:jedis:2.3.1' :war |
| | | - compile 'ro.fortsoft.pf4j:pf4j:0.8.0' :war |
| | | - compile 'org.apache.tika:tika-core:1.5' :war |
| | | - compile 'org.jsoup:jsoup:1.7.3' :war |
| | | - test 'junit' |
| | | # Dependencies for Selenium web page testing |
| | | - test 'org.seleniumhq.selenium:selenium-java:${selenium.version}' @jar |
| | |
| | | </SOURCES> |
| | | </library> |
| | | </orderEntry> |
| | | <orderEntry type="module-library"> |
| | | <library name="jsoup-1.7.3.jar"> |
| | | <CLASSES> |
| | | <root url="jar://$MODULE_DIR$/ext/jsoup-1.7.3.jar!/" /> |
| | | </CLASSES> |
| | | <JAVADOC /> |
| | | <SOURCES> |
| | | <root url="jar://$MODULE_DIR$/ext/src/jsoup-1.7.3.jar!/" /> |
| | | </SOURCES> |
| | | </library> |
| | | </orderEntry> |
| | | <orderEntry type="module-library" scope="TEST"> |
| | | <library name="junit-4.11.jar"> |
| | | <CLASSES> |
| | |
| | | import com.gitblit.transport.ssh.IPublicKeyManager; |
| | | import com.gitblit.transport.ssh.MemoryKeyManager; |
| | | import com.gitblit.transport.ssh.NullKeyManager; |
| | | import com.gitblit.utils.JSoupXssFilter; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.wicket.GitBlitWebApp; |
| | | |
| | | import dagger.Module; |
| | |
| | | library = true, |
| | | injects = { |
| | | IStoredSettings.class, |
| | | XssFilter.class, |
| | | |
| | | // core managers |
| | | IRuntimeManager.class, |
| | |
| | | return new FileSettings(); |
| | | } |
| | | |
| | | @Provides @Singleton IRuntimeManager provideRuntimeManager(IStoredSettings settings) { |
| | | return new RuntimeManager(settings); |
| | | @Provides @Singleton XssFilter provideXssFilter() { |
| | | return new JSoupXssFilter(); |
| | | } |
| | | |
| | | @Provides @Singleton IRuntimeManager provideRuntimeManager(IStoredSettings settings, XssFilter xssFilter) { |
| | | return new RuntimeManager(settings, xssFilter); |
| | | } |
| | | |
| | | @Provides @Singleton IPluginManager providePluginManager(IRuntimeManager runtimeManager) { |
| | |
| | | import com.gitblit.service.FederationPullService;
|
| | | import com.gitblit.utils.FederationUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.XssFilter;
|
| | | import com.gitblit.utils.XssFilter.AllowXssFilter;
|
| | |
|
| | | /**
|
| | | * Command-line client to pull federated Gitblit repositories.
|
| | |
| | | }
|
| | |
|
| | | // configure the Gitblit singleton for minimal, non-server operation
|
| | | RuntimeManager runtime = new RuntimeManager(settings, baseFolder).start();
|
| | | XssFilter xssFilter = new AllowXssFilter();
|
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, baseFolder).start();
|
| | | NoopNotificationManager notifications = new NoopNotificationManager().start();
|
| | | UserManager users = new UserManager(runtime, null).start();
|
| | | RepositoryManager repositories = new RepositoryManager(runtime, null, users).start();
|
| | |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.tickets.RedisTicketService; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * A command-line tool to move all tickets from one ticket service to another. |
| | |
| | | settings.overrideSetting(Keys.web.activityCacheDays, 0); |
| | | settings.overrideSetting(ITicketService.SETTING_UPDATE_DIFFSTATS, false); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter, baseFolder).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start(); |
| | | |
| | | String inputServiceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName()); |
| | |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.tickets.RedisTicketService; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * A command-line tool to reindex all tickets in all repositories when the |
| | |
| | | settings.overrideSetting(Keys.git.enableMirroring, false); |
| | | settings.overrideSetting(Keys.web.activityCacheDays, 0); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter, baseFolder).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start(); |
| | | |
| | | String serviceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName()); |
| | |
| | | import com.gitblit.transport.ssh.IPublicKeyManager; |
| | | import com.gitblit.transport.ssh.SshKey; |
| | | import com.gitblit.utils.ArrayUtils; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.HttpUtils; |
| | | import com.gitblit.utils.JsonUtils; |
| | | import com.gitblit.utils.ObjectCache; |
| | |
| | | return runtimeManager.getStatus(); |
| | | } |
| | | |
| | | @Override |
| | | public XssFilter getXssFilter() { |
| | | return runtimeManager.getXssFilter(); |
| | | } |
| | | |
| | | /* |
| | | * NOTIFICATION MANAGER |
| | | */ |
| | |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.models.ServerSettings; |
| | | import com.gitblit.models.ServerStatus; |
| | | import com.gitblit.utils.XssFilter; |
| | | |
| | | public interface IRuntimeManager extends IManager { |
| | | |
| | |
| | | * @since 1.4.0 |
| | | */ |
| | | boolean updateSettings(Map<String, String> updatedSettings); |
| | | |
| | | /** |
| | | * Returns the HTML sanitizer used to clean user content. |
| | | * |
| | | * @return the HTML sanitizer |
| | | */ |
| | | XssFilter getXssFilter(); |
| | | } |
| | |
| | | import com.gitblit.models.ServerStatus; |
| | | import com.gitblit.models.SettingModel; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.utils.XssFilter; |
| | | |
| | | public class RuntimeManager implements IRuntimeManager { |
| | | |
| | | private final Logger logger = LoggerFactory.getLogger(getClass()); |
| | | |
| | | private final IStoredSettings settings; |
| | | |
| | | private final XssFilter xssFilter; |
| | | |
| | | private final ServerStatus serverStatus; |
| | | |
| | |
| | | |
| | | private TimeZone timezone; |
| | | |
| | | public RuntimeManager(IStoredSettings settings) { |
| | | this(settings, null); |
| | | public RuntimeManager(IStoredSettings settings, XssFilter xssFilter) { |
| | | this(settings, xssFilter, null); |
| | | } |
| | | |
| | | public RuntimeManager(IStoredSettings settings, File baseFolder) { |
| | | public RuntimeManager(IStoredSettings settings, XssFilter xssFilter, File baseFolder) { |
| | | this.settings = settings; |
| | | this.settingsModel = new ServerSettings(); |
| | | this.serverStatus = new ServerStatus(); |
| | | this.xssFilter = xssFilter; |
| | | this.baseFolder = baseFolder == null ? new File("") : baseFolder; |
| | | } |
| | | |
| | |
| | | serverStatus.heapFree = Runtime.getRuntime().freeMemory(); |
| | | return serverStatus; |
| | | } |
| | | |
| | | /** |
| | | * Returns the XSS filter. |
| | | * |
| | | * @return the XSS filter |
| | | */ |
| | | @Override |
| | | public XssFilter getXssFilter() { |
| | | return xssFilter; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 gitblit.com. |
| | | * |
| | | * 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. |
| | | */ |
| | | package com.gitblit.utils; |
| | | |
| | | import org.jsoup.Jsoup; |
| | | import org.jsoup.nodes.Document; |
| | | import org.jsoup.safety.Cleaner; |
| | | import org.jsoup.safety.Whitelist; |
| | | |
| | | /** |
| | | * Implementation of an XSS filter based on JSoup. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class JSoupXssFilter implements XssFilter { |
| | | |
| | | private final Cleaner none; |
| | | |
| | | private final Cleaner relaxed; |
| | | |
| | | public JSoupXssFilter() { |
| | | none = new Cleaner(Whitelist.none()); |
| | | relaxed = new Cleaner(getRelaxedWhiteList()); |
| | | } |
| | | |
| | | @Override |
| | | public String none(String input) { |
| | | return clean(input, none); |
| | | } |
| | | |
| | | @Override |
| | | public String relaxed(String input) { |
| | | return clean(input, relaxed); |
| | | } |
| | | |
| | | protected String clean(String input, Cleaner cleaner) { |
| | | Document unsafe = Jsoup.parse(input); |
| | | Document safe = cleaner.clean(unsafe); |
| | | return safe.body().html(); |
| | | } |
| | | |
| | | /** |
| | | * Builds & returns a loose HTML whitelist similar to Github. |
| | | * |
| | | * https://github.com/github/markup/tree/master#html-sanitization |
| | | * @return a loose HTML whitelist |
| | | */ |
| | | protected Whitelist getRelaxedWhiteList() { |
| | | return new Whitelist() |
| | | .addTags( |
| | | "a", "b", "blockquote", "br", "caption", "cite", "code", "col", |
| | | "colgroup", "dd", "del", "div", "dl", "dt", "em", "h1", "h2", "h3", "h4", "h5", "h6", "hr", |
| | | "i", "img", "ins", "kbd", "li", "ol", "p", "pre", "q", "samp", "small", "strike", "strong", |
| | | "sub", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "tt", "u", |
| | | "ul", "var") |
| | | |
| | | .addAttributes("a", "href", "title") |
| | | .addAttributes("blockquote", "cite") |
| | | .addAttributes("col", "span", "width") |
| | | .addAttributes("colgroup", "span", "width") |
| | | .addAttributes("img", "align", "alt", "height", "src", "title", "width") |
| | | .addAttributes("ol", "start", "type") |
| | | .addAttributes("q", "cite") |
| | | .addAttributes("table", "summary", "width") |
| | | .addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width") |
| | | .addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope", "width") |
| | | .addAttributes("ul", "type") |
| | | |
| | | .addEnforcedAttribute("a", "rel", "nofollow") |
| | | ; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 gitblit.com. |
| | | * |
| | | * 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. |
| | | */ |
| | | package com.gitblit.utils; |
| | | |
| | | /** |
| | | * Defines the contract for an XSS filter implementation. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public interface XssFilter { |
| | | |
| | | /** |
| | | * Returns a filtered version of the input value that contains no html |
| | | * elements. |
| | | * |
| | | * @param input |
| | | * @return a plain text value |
| | | */ |
| | | String none(String input); |
| | | |
| | | /** |
| | | * Returns a filtered version of the input that contains structural html |
| | | * elements. |
| | | * |
| | | * @param input |
| | | * @return a filtered html value |
| | | */ |
| | | String relaxed(String input); |
| | | |
| | | /** |
| | | * A NOOP XSS filter. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class AllowXssFilter implements XssFilter { |
| | | |
| | | @Override |
| | | public String none(String input) { |
| | | return input; |
| | | } |
| | | |
| | | @Override |
| | | public String relaxed(String input) { |
| | | return input; |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | import com.gitblit.manager.IUserManager; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.transport.ssh.IPublicKeyManager; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.wicket.pages.ActivityPage; |
| | | import com.gitblit.wicket.pages.BlamePage; |
| | | import com.gitblit.wicket.pages.BlobDiffPage; |
| | |
| | | |
| | | private final IStoredSettings settings; |
| | | |
| | | private final XssFilter xssFilter; |
| | | |
| | | private final IRuntimeManager runtimeManager; |
| | | |
| | | private final IPluginManager pluginManager; |
| | |
| | | |
| | | super(); |
| | | this.settings = runtimeManager.getSettings(); |
| | | this.xssFilter = runtimeManager.getXssFilter(); |
| | | this.runtimeManager = runtimeManager; |
| | | this.pluginManager = pluginManager; |
| | | this.notificationManager = notificationManager; |
| | |
| | | if (!settings.getBoolean(Keys.web.mountParameters, true)) { |
| | | parameters = new String[] {}; |
| | | } |
| | | mount(new GitblitParamUrlCodingStrategy(settings, location, clazz, parameters)); |
| | | mount(new GitblitParamUrlCodingStrategy(settings, xssFilter, location, clazz, parameters)); |
| | | |
| | | // map the mount point to the cache control definition |
| | | if (clazz.isAnnotationPresent(CacheControl.class)) { |
| | |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#xssFilter() |
| | | */ |
| | | @Override |
| | | public XssFilter xssFilter() { |
| | | return xssFilter; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#isDebugMode() |
| | | */ |
| | | @Override |
| | |
| | | */
|
| | | package com.gitblit.wicket;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.HashSet;
|
| | | import java.util.Map;
|
| | | import java.util.Set;
|
| | |
|
| | | import org.apache.wicket.IRequestTarget;
|
| | | import org.apache.wicket.Page;
|
| | | import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy; |
| | | import org.apache.wicket.request.RequestParameters;
|
| | | import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
|
| | | import org.apache.wicket.util.string.AppendingStringBuffer;
|
| | |
| | |
|
| | | import com.gitblit.IStoredSettings;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.utils.XssFilter; |
| | |
|
| | | /**
|
| | | * Simple subclass of mixed parameter url coding strategy that works around the
|
| | |
| | |
|
| | | private IStoredSettings settings;
|
| | |
|
| | | private XssFilter xssFilter; |
| | | |
| | | /**
|
| | | * Construct.
|
| | | *
|
| | |
| | | */
|
| | | public <C extends Page> GitblitParamUrlCodingStrategy(
|
| | | IStoredSettings settings,
|
| | | XssFilter xssFilter, |
| | | String mountPath,
|
| | | Class<C> bookmarkablePageClass, String[] parameterNames) {
|
| | |
|
| | | super(mountPath, bookmarkablePageClass, parameterNames);
|
| | | this.parameterNames = parameterNames;
|
| | | this.settings = settings;
|
| | | this.xssFilter = xssFilter; |
| | | }
|
| | |
|
| | | /**
|
| | |
| | | */
|
| | | @Override
|
| | | public IRequestTarget decode(RequestParameters requestParameters) {
|
| | | final String parametersFragment = requestParameters.getPath().substring(
|
| | | getMountPath().length());
|
| | | logger.debug(MessageFormat
|
| | | .format("REQ: {0} PARAMS {1}", getMountPath(), parametersFragment));
|
| | | Map<String, Object> parameterMap = (Map<String, Object>) requestParameters.getParameters(); |
| | | for (Map.Entry<String, Object> entry : parameterMap.entrySet()) { |
| | | String parameter = entry.getKey(); |
| | | if (parameter.startsWith(WebRequestCodingStrategy.NAME_SPACE)) { |
| | | // ignore Wicket parameters |
| | | continue; |
| | | } |
| | | |
| | | // sanitize Gitblit request parameters |
| | | Object o = entry.getValue(); |
| | | if (o instanceof String) { |
| | | String value = o.toString(); |
| | | String safeValue = xssFilter.none(value); |
| | | if (!value.equals(safeValue)) { |
| | | logger.warn("XSS filter triggered on {} URL parameter: {}={}", |
| | | getMountPath(), parameter, value); |
| | | parameterMap.put(parameter, safeValue); |
| | | } |
| | | } else if (o instanceof String[]) { |
| | | String[] values = (String[]) o; |
| | | for (int i = 0; i < values.length; i++) { |
| | | String value = values[i].toString(); |
| | | String safeValue = xssFilter.none(value); |
| | | if (!value.equals(safeValue)) { |
| | | logger.warn("XSS filter triggered on {} URL parameter: {}={}", |
| | | getMountPath(), parameter, value); |
| | | values[i] = safeValue; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
|
| | | return super.decode(requestParameters);
|
| | | }
|
| | |
| | | import com.gitblit.manager.IUserManager; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.transport.ssh.IPublicKeyManager; |
| | | import com.gitblit.utils.XssFilter; |
| | | |
| | | public interface GitblitWicketApp { |
| | | |
| | |
| | | |
| | | public abstract IStoredSettings settings(); |
| | | |
| | | public abstract XssFilter xssFilter(); |
| | | |
| | | /** |
| | | * Is Gitblit running in debug mode? |
| | | * |
| | |
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.wicket.pages.DocPage;
|
| | | import com.google.common.base.Joiner;
|
| | |
|
| | |
| | |
|
| | | private final IStoredSettings settings;
|
| | |
|
| | | public MarkupProcessor(IStoredSettings settings) {
|
| | | this.settings = settings;
|
| | | }
|
| | | private final XssFilter xssFilter; |
| | |
|
| | | public List<String> getMarkupExtensions() {
|
| | | public static List<String> getMarkupExtensions(IStoredSettings settings) { |
| | | List<String> list = new ArrayList<String>();
|
| | | list.addAll(settings.getStrings(Keys.web.confluenceExtensions));
|
| | | list.addAll(settings.getStrings(Keys.web.markdownExtensions));
|
| | |
| | | return list;
|
| | | }
|
| | |
|
| | | public MarkupProcessor(IStoredSettings settings, XssFilter xssFilter) { |
| | | this.settings = settings; |
| | | this.xssFilter = xssFilter; |
| | | } |
| | | |
| | | public List<String> getMarkupExtensions() { |
| | | return getMarkupExtensions(settings); |
| | | } |
| | | |
| | | public List<String> getAllExtensions() {
|
| | | List<String> list = getMarkupExtensions();
|
| | | List<String> list = getMarkupExtensions(settings); |
| | | list.add("txt");
|
| | | list.add("TXT");
|
| | | return list;
|
| | |
| | | MarkupParser parser = new MarkupParser(lang);
|
| | | parser.setBuilder(builder);
|
| | | parser.parse(doc.markup);
|
| | | doc.html = writer.toString();
|
| | | |
| | | final String content = writer.toString(); |
| | | final String safeContent = xssFilter.relaxed(content); |
| | | |
| | | doc.html = safeContent; |
| | | }
|
| | |
|
| | | /**
|
| | |
| | | return new Rendering(url, name);
|
| | | }
|
| | | };
|
| | | doc.html = MarkdownUtils.transformMarkdown(doc.markup, renderer);
|
| | | |
| | | final String content = MarkdownUtils.transformMarkdown(doc.markup, renderer); |
| | | final String safeContent = xssFilter.relaxed(content); |
| | | |
| | | doc.html = safeContent; |
| | | }
|
| | |
|
| | | private String getWicketUrl(Class<? extends Page> pageClass, final String repositoryName, final String commitId, final String document) {
|
New file |
| | |
| | | package com.gitblit.wicket; |
| | | |
| | | import org.apache.wicket.model.IModel; |
| | | import org.apache.wicket.model.Model; |
| | | import org.apache.wicket.util.lang.Objects; |
| | | import org.parboiled.common.StringUtils; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | public class SafeTextModel implements IModel<String> { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public enum Mode { |
| | | relaxed, none |
| | | } |
| | | |
| | | private final Mode mode; |
| | | |
| | | private String value; |
| | | |
| | | public static SafeTextModel none() { |
| | | return new SafeTextModel(Mode.none); |
| | | } |
| | | |
| | | public static SafeTextModel none(String value) { |
| | | return new SafeTextModel(Mode.none); |
| | | } |
| | | |
| | | public static SafeTextModel relaxed() { |
| | | return new SafeTextModel(Mode.relaxed); |
| | | } |
| | | |
| | | public static SafeTextModel relaxed(String value) { |
| | | return new SafeTextModel(Mode.relaxed); |
| | | } |
| | | |
| | | public SafeTextModel(Mode mode) { |
| | | this.mode = mode; |
| | | } |
| | | |
| | | public SafeTextModel(String value, Mode mode) { |
| | | this.value = value; |
| | | this.mode = mode; |
| | | } |
| | | |
| | | @Override |
| | | public void detach() { |
| | | } |
| | | |
| | | @Override |
| | | public String getObject() { |
| | | if (StringUtils.isEmpty(value)) { |
| | | return value; |
| | | } |
| | | String safeValue; |
| | | switch (mode) { |
| | | case none: |
| | | safeValue = GitBlitWebApp.get().xssFilter().none(value); |
| | | break; |
| | | default: |
| | | safeValue = GitBlitWebApp.get().xssFilter().relaxed(value); |
| | | break; |
| | | } |
| | | if (!value.equals(safeValue)) { |
| | | LoggerFactory.getLogger(getClass()).warn("XSS filter trigggered on suspicious form field value {}", |
| | | value); |
| | | } |
| | | return safeValue; |
| | | } |
| | | |
| | | @Override |
| | | public void setObject(String input) { |
| | | this.value = input; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() |
| | | { |
| | | return Objects.hashCode(value); |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object obj) |
| | | { |
| | | if (this == obj) |
| | | { |
| | | return true; |
| | | } |
| | | if (!(obj instanceof Model<?>)) |
| | | { |
| | | return false; |
| | | } |
| | | Model<?> that = (Model<?>)obj; |
| | | return Objects.equal(value, that.getObject()); |
| | | } |
| | | } |
| | |
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.Constants.AccessPermission;
|
| | | import com.gitblit.Constants.FederationPullStatus;
|
| | | import com.gitblit.IStoredSettings;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.FederationModel;
|
| | | import com.gitblit.models.Metric;
|
| | |
| | | return newImage(wicketId, "file_settings_16x16.png");
|
| | | }
|
| | |
|
| | | MarkupProcessor processor = new MarkupProcessor(GitBlitWebApp.get().settings());
|
| | | String ext = StringUtils.getFileExtension(filename).toLowerCase();
|
| | | if (processor.getMarkupExtensions().contains(ext)) {
|
| | | IStoredSettings settings = GitBlitWebApp.get().settings();
|
| | | if (MarkupProcessor.getMarkupExtensions(settings).contains(ext)) {
|
| | | return newImage(wicketId, "file_world_16x16.png");
|
| | | }
|
| | | return newImage(wicketId, "file_16x16.png");
|
| | |
| | | }
|
| | |
|
| | | // see if we should redirect to the doc page
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings());
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings(), app().xssFilter());
|
| | | for (String ext : processor.getMarkupExtensions()) {
|
| | | if (ext.equals(extension)) {
|
| | | setResponsePage(DocPage.class, params);
|
| | |
| | | super(params);
|
| | |
|
| | | final String path = WicketUtils.getPath(params).replace("%2f", "/").replace("%2F", "/");
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings());
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings(), app().xssFilter());
|
| | |
|
| | | Repository r = getRepository();
|
| | | RevCommit commit = JGitUtils.getCommit(r, objectId);
|
| | |
| | | public DocsPage(PageParameters params) {
|
| | | super(params);
|
| | |
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings());
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings(), app().xssFilter());
|
| | |
|
| | | Repository r = getRepository();
|
| | | RevCommit head = JGitUtils.getCommit(r, null);
|
| | |
| | | import com.gitblit.tickets.TicketResponsible;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.SafeTextModel;
|
| | | import com.gitblit.wicket.SafeTextModel.Mode;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.MarkdownTextArea;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | typeModel = Model.of(ticket.type);
|
| | | titleModel = Model.of(ticket.title);
|
| | | topicModel = Model.of(ticket.topic == null ? "" : ticket.topic);
|
| | | titleModel = SafeTextModel.none(ticket.title);
|
| | | topicModel = SafeTextModel.none(ticket.topic == null ? "" : ticket.topic);
|
| | | responsibleModel = Model.of();
|
| | | milestoneModel = Model.of();
|
| | | mergeToModel = Model.of(ticket.mergeTo == null ? getRepositoryModel().mergeTo : ticket.mergeTo);
|
| | |
| | | form.add(new TextField<String>("title", titleModel));
|
| | | form.add(new TextField<String>("topic", topicModel));
|
| | |
|
| | | final IModel<String> markdownPreviewModel = new Model<String>();
|
| | | final SafeTextModel markdownPreviewModel = new SafeTextModel(Mode.none);
|
| | | descriptionPreview = new Label("descriptionPreview", markdownPreviewModel);
|
| | | descriptionPreview.setEscapeModelStrings(false);
|
| | | descriptionPreview.setOutputMarkupId(true);
|
| | |
| | | import com.gitblit.tickets.TicketResponsible;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.SafeTextModel;
|
| | | import com.gitblit.wicket.SafeTextModel.Mode;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.MarkdownTextArea;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | typeModel = Model.of(TicketModel.Type.defaultType);
|
| | | titleModel = Model.of();
|
| | | topicModel = Model.of();
|
| | | titleModel = SafeTextModel.none();
|
| | | topicModel = SafeTextModel.none();
|
| | | mergeToModel = Model.of(Repository.shortenRefName(getRepositoryModel().mergeTo));
|
| | | responsibleModel = Model.of();
|
| | | milestoneModel = Model.of();
|
| | |
| | | form.add(new TextField<String>("title", titleModel));
|
| | | form.add(new TextField<String>("topic", topicModel));
|
| | |
|
| | | final IModel<String> markdownPreviewModel = new Model<String>();
|
| | | final SafeTextModel markdownPreviewModel = new SafeTextModel(Mode.none);
|
| | | descriptionPreview = new Label("descriptionPreview", markdownPreviewModel);
|
| | | descriptionPreview.setEscapeModelStrings(false);
|
| | | descriptionPreview.setOutputMarkupId(true);
|
| | |
| | | String html;
|
| | | switch (model.commitMessageRenderer) {
|
| | | case MARKDOWN:
|
| | | html = MessageFormat.format("<div class='commit_message'>{0}</div>", content);
|
| | | String safeContent = app().xssFilter().relaxed(content);
|
| | | html = MessageFormat.format("<div class='commit_message'>{0}</div>", safeContent);
|
| | | break;
|
| | | default:
|
| | | html = MessageFormat.format("<pre class='commit_message'>{0}</pre>", content);
|
| | |
| | | MarkupDocument markupDoc = null;
|
| | | RevCommit head = JGitUtils.getCommit(r, null);
|
| | | if (head != null) {
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings());
|
| | | MarkupProcessor processor = new MarkupProcessor(app().settings(), app().xssFilter());
|
| | | markupDoc = processor.getReadme(r, repositoryName, getBestCommitId(head));
|
| | | }
|
| | | if (markupDoc == null || markupDoc.markup == null) {
|
| | |
| | | import org.apache.wicket.ajax.markup.html.form.AjaxButton; |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | import org.apache.wicket.markup.html.form.Form; |
| | | import org.apache.wicket.model.IModel; |
| | | import org.apache.wicket.model.Model; |
| | | |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.TicketModel; |
| | | import com.gitblit.models.TicketModel.Change; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.wicket.SafeTextModel; |
| | | import com.gitblit.wicket.SafeTextModel.Mode; |
| | | import com.gitblit.wicket.WicketUtils; |
| | | import com.gitblit.wicket.pages.BasePage; |
| | | |
| | |
| | | } |
| | | }.setVisible(ticket != null && ticket.number > 0)); |
| | | |
| | | final IModel<String> markdownPreviewModel = new Model<String>(); |
| | | final SafeTextModel markdownPreviewModel = new SafeTextModel(Mode.none); |
| | | markdownPreview = new Label("markdownPreview", markdownPreviewModel); |
| | | markdownPreview.setEscapeModelStrings(false); |
| | | markdownPreview.setOutputMarkupId(true); |
| | |
| | | import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | import org.apache.wicket.markup.html.form.TextArea; |
| | | import org.apache.wicket.model.IModel; |
| | | import org.apache.wicket.model.PropertyModel; |
| | | import org.apache.wicket.util.time.Duration; |
| | | |
| | | import com.gitblit.utils.MarkdownUtils; |
| | | import com.gitblit.wicket.GitBlitWebApp; |
| | | import com.gitblit.wicket.SafeTextModel; |
| | | |
| | | public class MarkdownTextArea extends TextArea { |
| | | |
| | |
| | | |
| | | protected String text = ""; |
| | | |
| | | public MarkdownTextArea(String id, final IModel<String> previewModel, final Label previewLabel) { |
| | | public MarkdownTextArea(String id, final SafeTextModel previewModel, final Label previewLabel) { |
| | | super(id); |
| | | setModel(new PropertyModel(this, "text")); |
| | | add(new AjaxFormComponentUpdatingBehavior("onblur") { |
| | |
| | | setOutputMarkupId(true); |
| | | } |
| | | |
| | | protected void renderPreview(IModel<String> previewModel) { |
| | | protected void renderPreview(SafeTextModel previewModel) { |
| | | if (text == null) { |
| | | return; |
| | | } |
| | |
| | | import com.gitblit.manager.UserManager; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.tests.mock.MemorySettings; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * Class for testing local authentication. |
| | |
| | | } |
| | | |
| | | IAuthenticationManager newAuthenticationManager() { |
| | | RuntimeManager runtime = new RuntimeManager(getSettings(), GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(getSettings(), xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | users = new UserManager(runtime, null).start(); |
| | | AuthenticationManager auth = new AuthenticationManager(runtime, users).start(); |
| | | return auth; |
| | |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.tickets.BranchTicketService; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * Tests the branch ticket service. |
| | |
| | | protected ITicketService getService(boolean deleteAll) throws Exception { |
| | | |
| | | IStoredSettings settings = getSettings(deleteAll); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start(); |
| | | IPluginManager pluginManager = new PluginManager(runtimeManager).start(); |
| | | INotificationManager notificationManager = new NotificationManager(settings).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); |
| | |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.tickets.FileTicketService; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * Tests the file ticket service. |
| | |
| | | protected ITicketService getService(boolean deleteAll) throws Exception { |
| | | |
| | | IStoredSettings settings = getSettings(deleteAll); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start(); |
| | | IPluginManager pluginManager = new PluginManager(runtimeManager).start(); |
| | | INotificationManager notificationManager = new NotificationManager(settings).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); |
| | |
| | | import com.gitblit.manager.UserManager; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.tests.mock.MemorySettings; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * Test the Htpasswd user service. |
| | |
| | | } |
| | | |
| | | private HtpasswdAuthProvider newHtpasswdAuthentication(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | HtpasswdAuthProvider htpasswd = new HtpasswdAuthProvider(); |
| | | htpasswd.setup(runtime, users); |
| | |
| | | } |
| | | |
| | | private AuthenticationManager newAuthenticationManager(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | HtpasswdAuthProvider htpasswd = new HtpasswdAuthProvider(); |
| | | htpasswd.setup(runtime, users); |
| | |
| | | import com.gitblit.models.TeamModel; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.tests.mock.MemorySettings; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | import com.unboundid.ldap.listener.InMemoryDirectoryServer; |
| | | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; |
| | | import com.unboundid.ldap.listener.InMemoryListenerConfig; |
| | |
| | | } |
| | | |
| | | private LdapAuthProvider newLdapAuthentication(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | userManager = new UserManager(runtime, null).start(); |
| | | LdapAuthProvider ldap = new LdapAuthProvider(); |
| | | ldap.setup(runtime, userManager); |
| | |
| | | } |
| | | |
| | | private AuthenticationManager newAuthenticationManager(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | AuthenticationManager auth = new AuthenticationManager(runtime, userManager); |
| | | auth.addAuthenticationProvider(newLdapAuthentication(settings)); |
| | | return auth; |
| | |
| | | import com.gitblit.tests.mock.MemorySettings;
|
| | | import com.gitblit.utils.FileUtils;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.XssFilter;
|
| | | import com.gitblit.utils.XssFilter.AllowXssFilter;
|
| | |
|
| | | /**
|
| | | * Tests Lucene indexing and querying.
|
| | |
| | | private LuceneService newLuceneExecutor() {
|
| | | MemorySettings settings = new MemorySettings();
|
| | | settings.put(Keys.git.repositoriesFolder, GitBlitSuite.REPOSITORIES);
|
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
|
| | | XssFilter xssFilter = new AllowXssFilter();
|
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
|
| | | UserManager users = new UserManager(runtime, null).start();
|
| | | RepositoryManager repos = new RepositoryManager(runtime, null, users);
|
| | | return new LuceneService(settings, repos);
|
| | |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.tickets.RedisTicketService; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | /** |
| | | * Tests the Redis ticket service. |
| | |
| | | protected ITicketService getService(boolean deleteAll) throws Exception { |
| | | |
| | | IStoredSettings settings = getSettings(deleteAll); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start(); |
| | | IPluginManager pluginManager = new PluginManager(runtimeManager).start(); |
| | | INotificationManager notificationManager = new NotificationManager(settings).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); |
| | |
| | | import com.gitblit.manager.UserManager; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.tests.mock.MemorySettings; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | public class RedmineAuthenticationTest extends GitblitUnitTest { |
| | | |
| | |
| | | } |
| | | |
| | | RedmineAuthProvider newRedmineAuthentication(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | RedmineAuthProvider redmine = new RedmineAuthProvider(); |
| | | redmine.setup(runtime, users); |
| | |
| | | } |
| | | |
| | | AuthenticationManager newAuthenticationManager() { |
| | | RuntimeManager runtime = new RuntimeManager(getSettings(), GitBlitSuite.BASEFOLDER).start(); |
| | | XssFilter xssFilter = new AllowXssFilter(); |
| | | RuntimeManager runtime = new RuntimeManager(getSettings(), xssFilter, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | RedmineAuthProvider redmine = new RedmineAuthProvider(); |
| | | redmine.setup(runtime, users); |
| | |
| | | import com.gitblit.models.ServerSettings; |
| | | import com.gitblit.models.ServerStatus; |
| | | import com.gitblit.models.SettingModel; |
| | | import com.gitblit.utils.XssFilter; |
| | | import com.gitblit.utils.XssFilter.AllowXssFilter; |
| | | |
| | | public class MockRuntimeManager implements IRuntimeManager { |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public XssFilter getXssFilter() { |
| | | return new AllowXssFilter(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateSettings(Map<String, String> updatedSettings) { |
| | | return settings.saveSettings(updatedSettings); |
| | | } |