Skip to content
Permalink
Browse files

Merge pull request #2170 from kzantow/JENKINS-33770-security-token-no…

…t-always-required

[FIX JENKINS-33770] Prevent unauthenticated user registration
  • Loading branch information
daniel-beck committed Mar 31, 2016
2 parents a9f1209 + 5d74d4b commit 360cfcdcc87f8f10c9041e3fedfbee522fc035ed
@@ -29,8 +29,6 @@
import hudson.Util;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.Descriptor;
import jenkins.install.InstallState;
import jenkins.install.SetupWizard;
import jenkins.model.Jenkins;
import hudson.model.ManagementLink;
import hudson.model.ModelObject;
@@ -261,16 +259,26 @@ private void loginAndTakeBack(StaplerRequest req, StaplerResponse rsp, User u) t
}

/**
* Creates an user account. Used by admins.
* Creates a user account. Used by admins.
*
* This version behaves differently from {@link #doCreateAccount(StaplerRequest, StaplerResponse)} in that
* this is someone creating another user.
*/
public void doCreateAccountByAdmin(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
createAccountByAdmin(req, rsp, "addUser.jelly", "."); // send the user back to the listing page on success
}

/**
* Creates a user account. Requires {@link Jenkins#ADMINISTER}
*/
@Restricted(NoExternalUse.class)
public User createAccountByAdmin(StaplerRequest req, StaplerResponse rsp, String addUserView, String successView) throws IOException, ServletException {
checkPermission(Jenkins.ADMINISTER);
if(createAccount(req, rsp, false, "addUser.jelly")!=null) {
rsp.sendRedirect("."); // send the user back to the listing page
User u = createAccount(req, rsp, false, addUserView);
if(u != null) {
rsp.sendRedirect(successView);
}
return u;
}

/**
@@ -280,36 +288,14 @@ public void doCreateAccountByAdmin(StaplerRequest req, StaplerResponse rsp) thro
* This can be run by anyone, but only to create the very first user account.
*/
public void doCreateFirstAccount(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
boolean inSetup = !Jenkins.getInstance().getInstallState().isSetupComplete();
if(!inSetup && hasSomeUser()) {
if(hasSomeUser()) {
rsp.sendError(SC_UNAUTHORIZED,"First user was already created");
return;
}

User admin = null;
try {
String view = "firstUser.jelly";
if(inSetup) {
admin = getUser(SetupWizard.initialSetupAdminUserName);
if(admin != null) {
admin.delete(); // assume the new user may well be 'admin'
}
view = "setupWizardFirstUser.jelly";
}

User u = createAccount(req, rsp, false, view);
if (u!=null) {
tryToMakeAdmin(u);
if(admin != null) {
admin = null;
}
Jenkins.getInstance().setInstallState(InstallState.CREATE_ADMIN_USER.getNextState());
loginAndTakeBack(req, rsp, u);
}
} finally {
if(admin != null) {
admin.save(); // recreate this initial user if something failed
}
User u = createAccount(req, rsp, false, "firstUser.jelly");
if (u!=null) {
tryToMakeAdmin(u);
loginAndTakeBack(req, rsp, u);
}
}

@@ -1,9 +1,7 @@
package jenkins.install;

import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;

@@ -16,44 +14,35 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import hudson.util.VersionNumber;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import hudson.BulkChange;
import hudson.FilePath;
import hudson.model.User;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.security.HudsonPrivateSecurityRealm;
import hudson.security.SecurityRealm;
import hudson.security.csrf.DefaultCrumbIssuer;
import hudson.util.HttpResponses;
import hudson.util.PluginServletFilter;
import hudson.util.VersionNumber;
import jenkins.model.Jenkins;
import jenkins.security.s2m.AdminWhitelistRule;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.HttpResponse;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Locale;
import java.util.UUID;
import java.util.logging.Logger;

/**
* A Jenkins instance used during first-run to provide a limited set of services while
* initial installation is in progress
*
* @since 2.0
*/
@Restricted(NoExternalUse.class)
public class SetupWizard {
/**
* The security token parameter name
@@ -131,11 +120,46 @@ public SetupWizard(Jenkins j) throws IOException, InterruptedException {
throw new AssertionError(e);
}
}

/**
* Called during the initial setup to create an admin user
*/
public void doCreateAdminUser(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
Jenkins j = Jenkins.getInstance();
j.checkPermission(Jenkins.ADMINISTER);

// This will be set up by default. if not, something changed, ok to fail
HudsonPrivateSecurityRealm securityRealm = (HudsonPrivateSecurityRealm)j.getSecurityRealm();

User admin = securityRealm.getUser(SetupWizard.initialSetupAdminUserName);
try {
if(admin != null) {
admin.delete(); // assume the new user may well be 'admin'
}

User u = securityRealm.createAccountByAdmin(req, rsp, "/jenkins/install/SetupWizard/setupWizardFirstUser.jelly", req.getContextPath() + "/");
if (u != null) {
if(admin != null) {
admin = null;
}

j.setInstallState(InstallState.CREATE_ADMIN_USER.getNextState());

// ... and then login
Authentication a = new UsernamePasswordAuthenticationToken(u.getId(),req.getParameter("password1"));
a = securityRealm.getSecurityComponents().manager.authenticate(a);
SecurityContextHolder.getContext().setAuthentication(a);
}
} finally {
if(admin != null) {
admin.save(); // recreate this initial user if something failed
}
}
}

/**
* Gets the file used to store the initial admin password
*/
@Restricted(NoExternalUse.class) // use by Jelly
public FilePath getInitialAdminPasswordFile() {
return jenkins.getRootPath().child("secrets/initialAdminPassword");
}
@@ -167,13 +191,9 @@ public void init(FilterConfig cfg) throws ServletException {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// As an extra measure of security, the install wizard generates a security token, and
// requires the user to enter it before proceeding through the installation. Once set
// we'll set a cookie so the subsequent operations succeed
// Force root requests to the setup wizard
if (request instanceof HttpServletRequest) {
HttpServletRequest req = (HttpServletRequest)request;
//if (!Pattern.compile(".*[.](css|ttf|gif|woff|eot|png|js)").matcher(req.getRequestURI()).matches()) {
// Allow js & css requests through
if((req.getContextPath() + "/").equals(req.getRequestURI())) {
chain.doFilter(new HttpServletRequestWrapper(req) {
public String getRequestURI() {
@@ -43,8 +43,8 @@
padding: 1px 8px;
}
</style>
<form action="${rootURL}/securityRealm/${action}" method="post">
<local:_entryForm host="${app.securityRealm}" title="${%Create First Admin User}" action="createFirstAccount" captcha="${false}" xmlns:local="/hudson/security/HudsonPrivateSecurityRealm" />
<form action="${rootURL}/setupWizard/createAdminUser" method="post">
<local:_entryForm it="${app.securityRealm}" host="${app.securityRealm}" title="${%Create First Admin User}" captcha="${false}" xmlns:local="/hudson/security/HudsonPrivateSecurityRealm" />
<script>
$('username').focus();
</script>
@@ -9,7 +9,7 @@ var jenkins = require('../util/jenkins');
*/
exports.saveFirstUser = function($form, success, error) {
jenkins.staplerPost(
'/securityRealm/createFirstAccount',
'/setupWizard/createAdminUser',
$form,
success, {
dataType: 'html',
@@ -3,7 +3,7 @@
</div>
<div class="modal-body">
<div class="jumbotron welcome-panel security-panel">
<iframe src="{{baseUrl}}/securityRealm/setupWizardFirstUser"></iframe>
<iframe src="{{baseUrl}}/setupWizard/setupWizardFirstUser"></iframe>
</div>
</div>
<div class="modal-footer">

0 comments on commit 360cfcd

Please sign in to comment.
You can’t perform that action at this time.