/* * Copyright 2011 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.git; import java.util.HashSet; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.ReceivePack; import org.eclipse.jgit.transport.resolver.ReceivePackFactory; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gitblit.Constants.Transport; import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.manager.IGitblit; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.transport.git.GitDaemonClient; import com.gitblit.transport.ssh.SshDaemonClient; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.StringUtils; /** * The receive pack factory creates the receive pack which processes pushes. * * @author James Moger * * @param the connection type */ public class GitblitReceivePackFactory implements ReceivePackFactory { protected final Logger logger = LoggerFactory.getLogger(GitblitReceivePackFactory.class); private final IStoredSettings settings; private final IGitblit gitblit; public GitblitReceivePackFactory(IGitblit gitblit) { super(); this.settings = gitblit.getSettings(); this.gitblit = gitblit; } @Override public ReceivePack create(X req, Repository db) throws ServiceNotEnabledException, ServiceNotAuthorizedException { UserModel user = UserModel.ANONYMOUS; String repositoryName = ""; String origin = ""; String gitblitUrl = ""; int timeout = 0; Transport transport = null; if (req instanceof HttpServletRequest) { // http/https request may or may not be authenticated HttpServletRequest client = (HttpServletRequest) req; repositoryName = client.getAttribute("gitblitRepositoryName").toString(); origin = client.getRemoteHost(); gitblitUrl = HttpUtils.getGitblitURL(client); // determine pushing user String username = client.getRemoteUser(); if (!StringUtils.isEmpty(username)) { UserModel u = gitblit.getUserModel(username); if (u != null) { user = u; } } // determine the transport if ("http".equals(client.getScheme())) { transport = Transport.HTTP; } else if ("https".equals(client.getScheme())) { transport = Transport.HTTPS; } } else if (req instanceof GitDaemonClient) { // git daemon request is always anonymous GitDaemonClient client = (GitDaemonClient) req; repositoryName = client.getRepositoryName(); origin = client.getRemoteAddress().getHostAddress(); // set timeout from Git daemon timeout = client.getDaemon().getTimeout(); transport = Transport.GIT; } else if (req instanceof SshDaemonClient) { // SSH request is always authenticated SshDaemonClient client = (SshDaemonClient) req; repositoryName = client.getRepositoryName(); origin = client.getRemoteAddress().toString(); user = client.getUser(); transport = Transport.SSH; } if (!acceptPush(transport)) { throw new ServiceNotAuthorizedException(); } boolean allowAnonymousPushes = settings.getBoolean(Keys.git.allowAnonymousPushes, false); if (!allowAnonymousPushes && UserModel.ANONYMOUS.equals(user)) { // prohibit anonymous pushes throw new ServiceNotEnabledException(); } String url = settings.getString(Keys.web.canonicalUrl, null); if (StringUtils.isEmpty(url)) { url = gitblitUrl; } final RepositoryModel repository = gitblit.getRepositoryModel(repositoryName); // Determine which receive pack to use for pushes final GitblitReceivePack rp; if (gitblit.getTicketService().isAcceptingNewPatchsets(repository)) { rp = new PatchsetReceivePack(gitblit, db, repository, user); } else { rp = new GitblitReceivePack(gitblit, db, repository, user); } rp.setGitblitUrl(url); rp.setRefLogIdent(new PersonIdent(user.username, user.username + "@" + origin)); rp.setTimeout(timeout); return rp; } protected boolean acceptPush(Transport byTransport) { if (byTransport == null) { logger.info("Unknown transport, push rejected!"); return false; } Set transports = new HashSet(); for (String value : gitblit.getSettings().getStrings(Keys.git.acceptedPushTransports)) { Transport transport = Transport.fromString(value); if (transport == null) { logger.info(String.format("Ignoring unknown registered transport %s", value)); continue; } transports.add(transport); } if (transports.isEmpty()) { // no transports are explicitly specified, all are acceptable return true; } // verify that the transport is permitted return transports.contains(byTransport); } }