Merge branch 'master' into security-master

This commit is contained in:
Jesse Glick committed 2017-09-06 14:46:25 -04:00
commit 4b319e7604
503 files changed
+9928 -1306

No files matched your search

Vendored
+1 -1
View File
@@ -39,7 +39,7 @@ for(i = 0; i < buildTypes.size(); i++) {
"MAVEN_OPTS=-Xmx1536m -Xms512m"]) {
// Actually run Maven!
// -Dmaven.repo.local=… tells Maven to create a subdir in the temporary directory for the local Maven repository
def mvnCmd = "mvn -Pdebug -U clean install javadoc:javadoc ${runTests ? '-Dmaven.test.failure.ignore' : '-DskipTests'} -V -B -Dmaven.repo.local=${pwd tmp: true}/m2repo -s settings-azure.xml -e"
def mvnCmd = "mvn -Pdebug -U javadoc:javadoc clean install ${runTests ? '-Dmaven.test.failure.ignore' : '-DskipTests'} -V -B -Dmaven.repo.local=${pwd tmp: true}/m2repo -s settings-azure.xml -e"
if(isUnix()) {
sh mvnCmd
sh 'test `git status --short | tee /dev/stderr | wc --bytes` -eq 0'
+2 -2
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.69-SNAPSHOT</version>
<version>2.78-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
@@ -55,7 +55,7 @@
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>1.2.0</version> <!-- TODO 1.3.0 requires Java 8 -->
<version>1.6.0</version>
<optional>true</optional> <!-- do not expose to core -->
</dependency>
<dependency>
+1 -1
View File
@@ -47,9 +47,9 @@ import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier;
import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.future.WaitableFuture;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.common.util.io.NoCloseInputStream;
import org.apache.sshd.common.util.io.NoCloseOutputStream;
import org.apache.sshd.common.util.security.SecurityUtils;
/**
* Implements SSH connection mode of {@link CLI}.
+21 -3
View File
@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.69-SNAPSHOT</version>
<version>2.78-SNAPSHOT</version>
</parent>
<artifactId>jenkins-core</artifactId>
@@ -39,7 +39,7 @@ THE SOFTWARE.
<properties>
<staplerFork>true</staplerFork>
<stapler.version>1.250</stapler.version>
<stapler.version>1.252</stapler.version>
<spring.version>2.5.6.SEC03</spring.version>
<groovy.version>2.4.11</groovy.version>
<!-- TODO: Actually many issues are being filtered by src/findbugs/findbugs-excludes.xml -->
@@ -95,6 +95,12 @@ THE SOFTWARE.
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<exclusions>
<exclusion> <!-- TODO it seems to want Guava 16; apparently it manages to run against 11 -->
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <!-- for compatibility only; all new code should use JNR -->
@@ -590,6 +596,12 @@ THE SOFTWARE.
<version>1.3.1-jenkins-1</version>
</dependency>
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
<!-- offline profiler API to put in the classpath if we need it -->
<!--dependency>
<groupId>com.yourkit.api</groupId>
@@ -602,6 +614,12 @@ THE SOFTWARE.
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<exclusions>
<exclusion> <!-- pick up from Stapler -->
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@@ -753,7 +771,7 @@ THE SOFTWARE.
<artifactItem>
<groupId>com.sun.winsw</groupId>
<artifactId>winsw</artifactId>
<version>2.1.0</version>
<version>2.1.2</version>
<classifier>bin</classifier>
<type>exe</type>
<outputDirectory>${project.build.outputDirectory}/windows-service</outputDirectory>
@@ -396,7 +396,7 @@ public final class ProxyConfiguration extends AbstractDescribableImpl<ProxyConfi
if (userName.indexOf('\\') >= 0){
final String domain = userName.substring(0, userName.indexOf('\\'));
final String user = userName.substring(userName.indexOf('\\') + 1);
return new NTCredentials(user, Secret.fromString(password).getPlainText(), domain, "");
return new NTCredentials(user, Secret.fromString(password).getPlainText(), "", domain);
} else {
return new UsernamePasswordCredentials(userName, Secret.fromString(password).getPlainText());
}
@@ -58,6 +58,7 @@ import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
@@ -307,6 +308,7 @@ public final class TcpSlaveAgentListener extends Thread {
* @since 1.653
*/
@Extension
@Symbol("ping")
public static class PingAgentProtocol extends AgentProtocol {
private final byte[] ping;
+36 -1
View File
@@ -50,8 +50,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import java.io.StringWriter;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
@@ -114,6 +119,8 @@ import org.apache.commons.io.IOUtils;
public final class XmlFile {
private final XStream xs;
private final File file;
private static final Map<Object, Void> beingWritten = Collections.synchronizedMap(new IdentityHashMap<>());
private static final ThreadLocal<File> writing = new ThreadLocal<>();
public XmlFile(File file) {
this(DEFAULT_XSTREAM,file);
@@ -168,7 +175,14 @@ public final class XmlFile {
AtomicFileWriter w = new AtomicFileWriter(file);
try {
w.write("<?xml version='1.0' encoding='UTF-8'?>\n");
xs.toXML(o,w);
beingWritten.put(o, null);
writing.set(file);
try {
xs.toXML(o, w);
} finally {
beingWritten.remove(o);
writing.set(null);
}
w.commit();
} catch(StreamException e) {
throw new IOException(e);
@@ -177,6 +191,27 @@ public final class XmlFile {
}
}
/**
* Provides an XStream replacement for an object unless a call to {@link #write} is currently in progress.
* As per JENKINS-45892 this may be used by any class which expects to be written at top level to an XML file
* but which cannot safely be serialized as a nested object (for example, because it expects some {@code onLoad} hook):
* implement a {@code writeReplace} method delegating to this method.
* The replacement need not be {@link Serializable} since it is only necessary for use from XStream.
* @param o an object ({@code this} from {@code writeReplace})
* @param replacement a supplier of a safely serializable replacement object with a {@code readResolve} method
* @return {@code o}, if {@link #write} is being called on it, else the replacement
* @since 2.74
*/
public static Object replaceIfNotAtTopLevel(Object o, Supplier<Object> replacement) {
File currentlyWriting = writing.get();
if (beingWritten.containsKey(o) || currentlyWriting == null) {
return o;
} else {
LOGGER.log(Level.WARNING, "JENKINS-45892: reference to " + o + " being saved from unexpected " + currentlyWriting, new IllegalStateException());
return replacement.get();
}
}
public boolean exists() {
return file.exists();
}
@@ -47,12 +47,17 @@ public class CliProtocol extends AgentProtocol {
return jenkins.CLI.get().isEnabled() ? "CLI-connect" : null;
}
@Override
public boolean isDeprecated() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public String getDisplayName() {
return "Jenkins CLI Protocol/1";
return "Jenkins CLI Protocol/1 (deprecated, unencrypted)";
}
@Override
@@ -38,12 +38,18 @@ public class CliProtocol2 extends CliProtocol {
return false;
}
@Override
public boolean isDeprecated() {
// We do not recommend it though it may be required for Remoting CLI
return true;
}
/**
* {@inheritDoc}
*/
@Override
public String getDisplayName() {
return "Jenkins CLI Protocol/2";
return "Jenkins CLI Protocol/2 (deprecated)";
}
@Override
@@ -10,7 +10,7 @@ import java.util.List;
/**
* {@link CLICommand} that acts on a series of {@link Run}s.
* @since FIXME
* @since 2.62
*/
public abstract class RunRangeCommand extends CLICommand {
@Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0)
@@ -40,7 +40,7 @@ import org.jenkinsci.Symbol;
*
* @author Kohsuke Kawaguchi
* @since 1.349 - produces search hyperlinks to the http://stacktrace.jenkins-ci.org service
* @since TODO - does nothing due to JENKINS-42861
* @since 2.56 - does nothing due to JENKINS-42861
* @deprecated This ConsoleNote used to provide hyperlinks to the
* <code>http://stacktrace.jenkins-ci.org/</code> service, which is dead now (JENKINS-42861).
* This console note does nothing right now.
@@ -82,7 +82,7 @@ public enum InitMilestone implements Milestone {
* By this milestone, all programmatically constructed extension point implementations
* should be added.
*/
EXTENSIONS_AUGMENTED("Augmented all extensions"),
EXTENSIONS_AUGMENTED("Augmented all extensions"), // TODO nothing attains() this so when does it actually happen?
/**
* By this milestone, all jobs and their build records are loaded from disk.
@@ -60,20 +60,20 @@ public class WindowsServiceLifecycle extends Lifecycle {
*/
private void updateJenkinsExeIfNeeded() {
try {
File rootDir = Jenkins.getInstance().getRootDir();
File baseDir = getBaseDir();
URL exe = getClass().getResource("/windows-service/jenkins.exe");
String ourCopy = Util.getDigestOf(exe.openStream());
for (String name : new String[]{"hudson.exe","jenkins.exe"}) {
try {
File currentCopy = new File(rootDir,name);
File currentCopy = new File(baseDir,name);
if(!currentCopy.exists()) continue;
String curCopy = new FilePath(currentCopy).digest();
if(ourCopy.equals(curCopy)) continue; // identical
File stage = new File(rootDir,name+".new");
File stage = new File(baseDir,name+".new");
FileUtils.copyURLToFile(exe,stage);
Kernel32.INSTANCE.MoveFileExA(stage.getAbsolutePath(),currentCopy.getAbsolutePath(),MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING);
LOGGER.info("Scheduled a replacement of "+name);
@@ -107,8 +107,8 @@ public class WindowsServiceLifecycle extends Lifecycle {
String baseName = dest.getName();
baseName = baseName.substring(0,baseName.indexOf('.'));
File rootDir = Jenkins.getInstance().getRootDir();
File copyFiles = new File(rootDir,baseName+".copies");
File baseDir = getBaseDir();
File copyFiles = new File(baseDir,baseName+".copies");
try (FileWriter w = new FileWriter(copyFiles, true)) {
w.write(by.getAbsolutePath() + '>' + getHudsonWar().getAbsolutePath() + '\n');
@@ -144,6 +144,19 @@ public class WindowsServiceLifecycle extends Lifecycle {
if(r!=0)
throw new IOException(baos.toString());
}
private static final File getBaseDir() {
File baseDir;
String baseEnv = System.getenv("BASE");
if (baseEnv != null) {
baseDir = new File(baseEnv);
} else {
LOGGER.log(Level.WARNING, "Could not find environment variable 'BASE' for Jenkins base directory. Falling back to JENKINS_HOME");
baseDir = Jenkins.getInstance().getRootDir();
}
return baseDir;
}
private static final Logger LOGGER = Logger.getLogger(WindowsServiceLifecycle.class.getName());
}
@@ -324,6 +324,12 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
return culprits;
}
@Override
@Exported
@Nonnull public Set<User> getCulprits() {
return RunWithSCM.super.getCulprits();
}
@Override
public boolean shouldCalculateCulprits() {
return getCulpritIds() == null;
@@ -337,7 +343,7 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
AbstractBuild<P,R> p = getPreviousCompletedBuild();
if (upstreamCulprits) {
// If we have dependencies since the last successful build, add their authors to our list
if (p.getPreviousNotFailedBuild() != null) {
if (p != null && p.getPreviousNotFailedBuild() != null) {
Map<AbstractProject, AbstractBuild.DependencyChange> depmap =
p.getDependencyChanges(p.getPreviousSuccessfulBuild());
for (AbstractBuild.DependencyChange dep : depmap.values()) {
@@ -492,20 +492,6 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
return Jenkins.getInstance().getAuthorizationStrategy().getACL(this);
}
/**
* Short for {@code getACL().checkPermission(p)}
*/
public void checkPermission(Permission p) {
getACL().checkPermission(p);
}
/**
* Short for {@code getACL().hasPermission(p)}
*/
public boolean hasPermission(Permission p) {
return getACL().hasPermission(p);
}
/**
* Save the settings to a file.
*/
@@ -519,6 +505,24 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
return Items.getConfigFile(this);
}
private Object writeReplace() {
return XmlFile.replaceIfNotAtTopLevel(this, () -> new Replacer(this));
}
private static class Replacer {
private final String fullName;
Replacer(AbstractItem i) {
fullName = i.getFullName();
}
private Object readResolve() {
Jenkins j = Jenkins.getInstanceOrNull();
if (j == null) {
return null;
}
// Will generally only work if called after job loading:
return j.getItemByFullName(fullName);
}
}
public Descriptor getDescriptorByName(String className) {
return Jenkins.getInstance().getDescriptorByName(className);
}
@@ -74,12 +74,15 @@ public abstract class Actionable extends AbstractModelObject implements ModelObj
@Deprecated
@Nonnull
public List<Action> getActions() {
synchronized (this) {
if(actions == null) {
actions = new CopyOnWriteArrayList<Action>();
//this double checked synchronization is only safe if the field 'actions' is volatile
if (actions == null) {
synchronized (this) {
if (actions == null) {
actions = new CopyOnWriteArrayList<Action>();
}
}
return actions;
}
return actions;
}
/**
@@ -332,14 +332,6 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
return Jenkins.getInstance().getAuthorizationStrategy().getACL(this);
}
public void checkPermission(Permission permission) {
getACL().checkPermission(permission);
}
public boolean hasPermission(Permission permission) {
return getACL().hasPermission(permission);
}
/**
* If the computer was offline (either temporarily or not),
* this method will return the cause.
@@ -976,7 +968,7 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
* Gets the read-only snapshot view of all {@link Executor} instances including {@linkplain OneOffExecutor}s.
*
* @return the read-only snapshot view of all {@link Executor} instances including {@linkplain OneOffExecutor}s.
* @since TODO
* @since 2.55
*/
public List<Executor> getAllExecutors() {
List<Executor> result = new ArrayList<>(executors.size() + oneOffExecutors.size());
@@ -40,7 +40,9 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
@@ -130,18 +132,6 @@ public class DownloadService extends PageDecorator {
}
private String mapHttps(String url) {
/*
HACKISH:
Loading scripts in HTTP from HTTPS pages cause browsers to issue a warning dialog.
The elegant way to solve the problem is to always load update center from HTTPS,
but our backend mirroring scheme isn't ready for that. So this hack serves regular
traffic in HTTP server, and only use HTTPS update center for Jenkins in HTTPS.
We'll monitor the traffic to see if we can sustain this added traffic.
*/
if (url.startsWith("http://updates.jenkins-ci.org/") && Jenkins.getInstance().isRootUrlSecure())
return "https"+url.substring(4);
return url;
}
@@ -169,7 +159,12 @@ public class DownloadService extends PageDecorator {
*/
@Restricted(NoExternalUse.class)
public static String loadJSON(URL src) throws IOException {
try (InputStream is = ProxyConfiguration.open(src).getInputStream()) {
URLConnection con = ProxyConfiguration.open(src);
if (con instanceof HttpURLConnection) {
// prevent problems from misbehaving plugins disabling redirects by default
((HttpURLConnection) con).setInstanceFollowRedirects(true);
}
try (InputStream is = con.getInputStream()) {
String jsonp = IOUtils.toString(is, "UTF-8");
int start = jsonp.indexOf('{');
int end = jsonp.lastIndexOf('}');
@@ -189,7 +184,12 @@ public class DownloadService extends PageDecorator {
*/
@Restricted(NoExternalUse.class)
public static String loadJSONHTML(URL src) throws IOException {
try (InputStream is = ProxyConfiguration.open(src).getInputStream()) {
URLConnection con = ProxyConfiguration.open(src);
if (con instanceof HttpURLConnection) {
// prevent problems from misbehaving plugins disabling redirects by default
((HttpURLConnection) con).setInstanceFollowRedirects(true);
}
try (InputStream is = con.getInputStream()) {
String jsonp = IOUtils.toString(is, "UTF-8");
String preamble = "window.parent.postMessage(JSON.stringify(";
int start = jsonp.indexOf(preamble);
@@ -24,9 +24,14 @@
package hudson.model;
import hudson.EnvVars;
import hudson.Util;
import hudson.model.Queue.Task;
import hudson.tasks.Builder;
import hudson.tasks.BuildWrapper;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.ProtectedExternally;
import javax.annotation.Nonnull;
/**
* {@link Action} that contributes environment variables during a build.
@@ -40,17 +45,43 @@ import hudson.tasks.BuildWrapper;
*
* @author Kohsuke Kawaguchi
* @since 1.318
* @see AbstractBuild#getEnvironment(TaskListener)
* @see Run#getEnvironment(TaskListener)
* @see BuildWrapper
*/
public interface EnvironmentContributingAction extends Action {
/**
* Called by {@link Run} to allow plugins to contribute environment variables.
*
* @param run
* The calling build. Never null.
* @param env
* Environment variables should be added to this map.
* @since 2.76
*/
default void buildEnvironment(@Nonnull Run<?, ?> run, @Nonnull EnvVars env) {
if (run instanceof AbstractBuild
&& Util.isOverridden(EnvironmentContributingAction.class,
getClass(), "buildEnvVars", AbstractBuild.class, EnvVars.class)) {
buildEnvVars((AbstractBuild) run, env);
}
}
/**
* Called by {@link AbstractBuild} to allow plugins to contribute environment variables.
*
* @deprecated Use {@link #buildEnvironment} instead
*
* @param build
* The calling build. Never null.
* @param env
* Environment variables should be added to this map.
*/
void buildEnvVars(AbstractBuild<?, ?> build, EnvVars env);
@Deprecated
@Restricted(ProtectedExternally.class)
default void buildEnvVars(AbstractBuild<?, ?> build, EnvVars env) {
if (Util.isOverridden(EnvironmentContributingAction.class,
getClass(), "buildEnvironment", Run.class, EnvVars.class)) {
buildEnvironment(build, env);
}
}
}
@@ -355,6 +355,10 @@ public class Executor extends Thread implements ModelObject {
LOGGER.log(FINE, getName()+" grabbed "+workUnit+" from queue");
SubTask task = workUnit.work;
Executable executable = task.createExecutable();
if (executable == null) {
String displayName = task instanceof Queue.Task ? ((Queue.Task) task).getFullDisplayName() : task.getDisplayName();
LOGGER.log(WARNING, "{0} cannot be run (for example because it is disabled)", displayName);
}
lock.writeLock().lock();
try {
Executor.this.executable = executable;
@@ -387,7 +391,7 @@ public class Executor extends Thread implements ModelObject {
// by tasks. In such case Jenkins starts the workUnit in order
// to report results to console outputs.
if (executable == null) {
throw new Error("The null Executable has been created for "+workUnit+". The task cannot be executed");
return;
}
if (executable instanceof Actionable) {
@@ -440,7 +444,7 @@ public class Executor extends Thread implements ModelObject {
LOGGER.log(FINE, getName()+" interrupted",e);
// die peacefully
} catch(Exception | Error e) {
LOGGER.log(SEVERE, "Unexpected executor death", e);
LOGGER.log(SEVERE, getName()+": Unexpected executor death", e);
} finally {
if (asynchronousExecution == null) {
finish2();
+65 -6
View File
@@ -120,6 +120,9 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
/**
* A job is an runnable entity under the monitoring of Hudson.
@@ -374,13 +377,15 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
* (in which case none of the node specific properties would be reflected in the resulting override.)
*/
public @Nonnull EnvVars getEnvironment(@CheckForNull Node node, @Nonnull TaskListener listener) throws IOException, InterruptedException {
EnvVars env;
EnvVars env = new EnvVars();
if (node!=null) {
if (node != null) {
final Computer computer = node.toComputer();
env = (computer != null) ? computer.buildEnvironment(listener) : new EnvVars();
} else {
env = new EnvVars();
if (computer != null) {
// we need to get computer environment to inherit platform details
env = computer.getEnvironment();
env.putAll(computer.buildEnvironment(listener));
}
}
env.putAll(getCharacteristicEnvVars());
@@ -1051,7 +1056,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
/**
* RSS feed for changes in this project.
*
* @since TODO
* @since 2.60
*/
public void doRssChangelog(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
class FeedItem {
@@ -1604,4 +1609,58 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
}
private final static HexStringConfidentialKey SERVER_COOKIE = new HexStringConfidentialKey(Job.class,"serverCookie",16);
/**
* Check new name for job
* @param newName - New name for job
* @return {@code true} - if newName occupied and user has permissions for this job
* {@code false} - if newName occupied and user hasn't permissions for this job
* {@code null} - if newName didn't occupied
*
* @throws Failure if the given name is not good
*/
@CheckForNull
@Restricted(NoExternalUse.class)
public Boolean checkIfNameIsUsed(@Nonnull String newName) throws Failure{
Item item = null;
Jenkins.checkGoodName(newName);
try {
item = getParent().getItem(newName);
} catch(AccessDeniedException ex) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " +
"User {2} has {3} permission, but no {4} for existing job with the same name",
new Object[] {this.getFullName(), newName, User.current().getFullName(), Item.DISCOVER.name, Item.READ.name} );
}
return true;
}
if (item != null) {
// User has Read permissions for existing job with the same name
return true;
} else {
SecurityContext initialContext = null;
try {
initialContext = hudson.security.ACL.impersonate(ACL.SYSTEM);
item = getParent().getItem(newName);
if (item != null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " +
"User {2} has no {3} permission for existing job with the same name",
new Object[] {this.getFullName(), newName, initialContext.getAuthentication().getName(), Item.DISCOVER.name} );
}
return false;
}
} finally {
if (initialContext != null) {
SecurityContextHolder.setContext(initialContext);
}
}
}
return null;
}
}
@@ -185,14 +185,6 @@ public class MyViewsProperty extends UserProperty implements ModifiableViewGroup
return user.getACL();
}
public void checkPermission(Permission permission) throws AccessDeniedException {
getACL().checkPermission(permission);
}
public boolean hasPermission(Permission permission) {
return getACL().hasPermission(permission);
}
///// Action methods /////
public String getDisplayName() {
return Messages.MyViewsProperty_DisplayName();
@@ -509,14 +509,6 @@ public abstract class Node extends AbstractModelObject implements Reconfigurable
return Jenkins.getInstance().getAuthorizationStrategy().getACL(this);
}
public final void checkPermission(Permission permission) {
getACL().checkPermission(permission);
}
public final boolean hasPermission(Permission permission) {
return getACL().hasPermission(permission);
}
public Node reconfigure(final StaplerRequest req, JSONObject form) throws FormException {
if (form==null) return null;
@@ -138,10 +138,11 @@ public class ParametersAction implements RunAction2, Iterable<ParameterValue>, Q
}
}
public void buildEnvVars(AbstractBuild<?,?> build, EnvVars env) {
@Override
public void buildEnvironment(Run<?,?> run, EnvVars env) {
for (ParameterValue p : getParameters()) {
if (p == null) continue;
p.buildEnvironment(build, env);
p.buildEnvironment(run, env);
}
}
@@ -316,8 +317,8 @@ public class ParametersAction implements RunAction2, Iterable<ParameterValue>, Q
return parameters;
}
String shouldKeepFlag = SystemProperties.getString(KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME);
if ("true".equalsIgnoreCase(shouldKeepFlag)) {
Boolean shouldKeepFlag = SystemProperties.optBoolean(KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME);
if (shouldKeepFlag != null && shouldKeepFlag.booleanValue()) {
return parameters;
}
@@ -326,7 +327,7 @@ public class ParametersAction implements RunAction2, Iterable<ParameterValue>, Q
for (ParameterValue v : this.parameters) {
if (this.parameterDefinitionNames.contains(v.getName()) || isSafeParameter(v.getName())) {
filteredParameters.add(v);
} else if ("false".equalsIgnoreCase(shouldKeepFlag)) {
} else if (shouldKeepFlag == null) {
LOGGER.log(Level.WARNING, "Skipped parameter `{0}` as it is undefined on `{1}`. Set `-D{2}=true` to allow "
+ "undefined parameters to be injected as environment variables or `-D{3}=[comma-separated list]` to whitelist specific parameter names, "
+ "even though it represents a security breach or `-D{2}=false` to no longer show this message.",
+5 -4
View File
@@ -1540,7 +1540,7 @@ public class Queue extends ResourceController implements Saveable {
continue;
}
String taskDisplayName = p.task.getFullDisplayName();
String taskDisplayName = LOGGER.isLoggable(Level.FINEST) ? p.task.getFullDisplayName() : null;
if (p.task instanceof FlyweightTask) {
Runnable r = makeFlyWeightTaskBuildable(new BuildableItem(p));
@@ -1617,7 +1617,7 @@ public class Queue extends ResourceController implements Saveable {
*/
private @CheckForNull Runnable makeBuildable(final BuildableItem p) {
if (p.task instanceof FlyweightTask) {
String taskDisplayName = p.task.getFullDisplayName();
String taskDisplayName = LOGGER.isLoggable(Level.FINEST) ? p.task.getFullDisplayName() : null;
if (!isBlockedByShutdown(p.task)) {
Runnable runnable = makeFlyWeightTaskBuildable(p);
@@ -1665,7 +1665,8 @@ public class Queue extends ResourceController implements Saveable {
hash.addAll(hashSource);
Label lbl = p.getAssignedLabel();
for (Node n : hash.list(p.task.getFullDisplayName())) {
String fullDisplayName = p.task.getFullDisplayName();
for (Node n : hash.list(fullDisplayName)) {
final Computer c = n.toComputer();
if (c == null || c.isOffline()) {
continue;
@@ -1677,7 +1678,7 @@ public class Queue extends ResourceController implements Saveable {
continue;
}
LOGGER.log(Level.FINEST, "Creating flyweight task {0} for computer {1}", new Object[]{p.task.getFullDisplayName(), c.getName()});
LOGGER.log(Level.FINEST, "Creating flyweight task {0} for computer {1}", new Object[]{fullDisplayName, c.getName()});
return new Runnable() {
@Override public void run() {
c.startFlyWeightTask(new WorkUnitContext(p).createWorkUnit(p.task));
+44 -21
View File
@@ -51,7 +51,6 @@ import hudson.cli.declarative.CLIMethod;
import hudson.model.Descriptor.FormException;
import hudson.model.listeners.RunListener;
import hudson.model.listeners.SaveableListener;
import hudson.model.queue.Executables;
import hudson.model.queue.SubTask;
import hudson.search.SearchIndexBuilder;
import hudson.security.ACL;
@@ -774,6 +773,9 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
@Override
public String toString() {
if (project == null) {
return "<broken data JENKINS-45892>";
}
return project.getFullName() + " #" + number;
}
@@ -1454,16 +1456,6 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
return new Api(this);
}
@Override
public void checkPermission(@Nonnull Permission p) {
getACL().checkPermission(p);
}
@Override
public boolean hasPermission(@Nonnull Permission p) {
return getACL().hasPermission(p);
}
@Override
public ACL getACL() {
// for now, don't maintain ACL per run, and do it at project level
@@ -1698,6 +1690,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
if(result!=null)
return; // already built.
OutputStream logger = null;
StreamBuildListener listener=null;
runner = job;
@@ -1716,7 +1709,8 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
charset = computer.getDefaultCharset();
this.charset = charset.name();
}
listener = createBuildListener(job, listener, charset);
logger = createLogger();
listener = createBuildListener(job, logger, charset);
listener.started(getCauses());
Authentication auth = Jenkins.getAuthentication();
@@ -1798,23 +1792,32 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
try {
getParent().logRotate();
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to rotate log",e);
}
LOGGER.log(Level.SEVERE, "Failed to rotate log",e);
}
} finally {
onEndBuilding();
if (logger != null) {
try {
logger.close();
} catch (IOException x) {
LOGGER.log(Level.WARNING, "failed to close log for " + Run.this, x);
}
}
}
}
private StreamBuildListener createBuildListener(@Nonnull RunExecution job, StreamBuildListener listener, Charset charset) throws IOException, InterruptedException {
private OutputStream createLogger() throws IOException {
// don't do buffering so that what's written to the listener
// gets reflected to the file immediately, which can then be
// served to the browser immediately
OutputStream logger;
try {
logger = Files.newOutputStream(getLogFile().toPath(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
return Files.newOutputStream(getLogFile().toPath(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (InvalidPathException e) {
throw new IOException(e);
}
}
private StreamBuildListener createBuildListener(@Nonnull RunExecution job, OutputStream logger, Charset charset) throws IOException, InterruptedException {
RunT build = job.getBuild();
// Global log filters
@@ -1830,8 +1833,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
}
}
listener = new StreamBuildListener(logger,charset);
return listener;
return new StreamBuildListener(logger,charset);
}
/**
@@ -1928,6 +1930,19 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
return new XmlFile(XSTREAM,new File(getRootDir(),"build.xml"));
}
private Object writeReplace() {
return XmlFile.replaceIfNotAtTopLevel(this, () -> new Replacer(this));
}
private static class Replacer {
private final String id;
Replacer(Run<?, ?> r) {
id = r.getExternalizableId();
}
private Object readResolve() {
return fromExternalizableId(id);
}
}
/**
* Gets the log of the build as a string.
* @return Returns the log or an empty string if it has not been found
@@ -2128,7 +2143,6 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
*/
public void doConsoleText(StaplerRequest req, StaplerResponse rsp) throws IOException {
rsp.setContentType("text/plain;charset=UTF-8");
;
try (InputStream input = getLogInputStream();
OutputStream os = rsp.getCompressedOutputStream(req);
PlainTextConsoleOutputStream out = new PlainTextConsoleOutputStream(os)) {
@@ -2277,6 +2291,12 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
for (EnvironmentContributor ec : EnvironmentContributor.all().reverseView())
ec.buildEnvironmentFor(this,env,listener);
if (!(this instanceof AbstractBuild)) {
for (EnvironmentContributingAction a : getActions(EnvironmentContributingAction.class)) {
a.buildEnvironment(this, env);
}
} // else for compatibility reasons, handled in override after buildEnvironments
return env;
}
@@ -2319,7 +2339,10 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
} catch (NumberFormatException x) {
throw new IllegalArgumentException(x);
}
Jenkins j = Jenkins.getInstance();
Jenkins j = Jenkins.getInstanceOrNull();
if (j == null) {
return null;
}
Job<?,?> job = j.getItemByFullName(jobName, Job.class);
if (job == null) {
return null;
+3 -2
View File
@@ -225,7 +225,8 @@ public abstract class Slave extends Node implements Serializable {
}
public ComputerLauncher getLauncher() {
return launcher == null ? new JNLPLauncher() : launcher;
// Default launcher does not use Work Directory
return launcher == null ? new JNLPLauncher(false) : launcher;
}
public void setLauncher(ComputerLauncher launcher) {
@@ -504,7 +505,7 @@ public abstract class Slave extends Node implements Serializable {
// convert the old format to the new one
if (launcher == null) {
launcher = (agentCommand == null || agentCommand.trim().length() == 0)
? new JNLPLauncher()
? new JNLPLauncher(false)
: new CommandLauncher(agentCommand);
}
if(nodeProperties==null)
@@ -148,7 +148,7 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
@ExportedBean
public class UpdateCenter extends AbstractModelObject implements Saveable, OnMaster {
private static final String UPDATE_CENTER_URL = SystemProperties.getString(UpdateCenter.class.getName()+".updateCenterUrl","http://updates.jenkins-ci.org/");
private static final String UPDATE_CENTER_URL = SystemProperties.getString(UpdateCenter.class.getName()+".updateCenterUrl","https://updates.jenkins.io/");
/**
* Read timeout when downloading plugins, defaults to 1 minute
@@ -485,18 +485,6 @@ public class UpdateSite {
*/
@Deprecated
public String getDownloadUrl() {
/*
HACKISH:
Loading scripts in HTTP from HTTPS pages cause browsers to issue a warning dialog.
The elegant way to solve the problem is to always load update center from HTTPS,
but our backend mirroring scheme isn't ready for that. So this hack serves regular
traffic in HTTP server, and only use HTTPS update center for Jenkins in HTTPS.
We'll monitor the traffic to see if we can sustain this added traffic.
*/
if (url.equals("http://updates.jenkins-ci.org/update-center.json") && Jenkins.getInstance().isRootUrlSecure())
return "https"+url.substring(4);
return url;
}
+72 -50
View File
@@ -34,6 +34,8 @@ import hudson.ExtensionPoint;
import hudson.FeedAdapter;
import hudson.Util;
import hudson.XmlFile;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.model.Descriptor.FormException;
import hudson.model.listeners.SaveableListener;
import hudson.security.ACL;
@@ -427,7 +429,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
byNameLock.readLock().lock();
User u;
try {
u = byName.get(idkey);
u = AllUsers.byName().get(idkey);
} finally {
byNameLock.readLock().unlock();
}
@@ -465,7 +467,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
User prev;
byNameLock.readLock().lock();
try {
prev = byName.putIfAbsent(idkey, u = tmp);
prev = AllUsers.byName().putIfAbsent(idkey, u = tmp);
} finally {
byNameLock.readLock().unlock();
}
@@ -535,36 +537,15 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
return getOrCreate(id, id, create);
}
private static volatile long lastScanned;
/**
* Gets all the users.
*/
public static @Nonnull Collection<User> getAll() {
final IdStrategy strategy = idStrategy();
if(System.currentTimeMillis() -lastScanned>10000) {
// occasionally scan the file system to check new users
// whether we should do this only once at start up or not is debatable.
// set this right away to avoid another thread from doing the same thing while we do this.
// having two threads doing the work won't cause race condition, but it's waste of time.
lastScanned = System.currentTimeMillis();
File[] subdirs = getRootDir().listFiles((FileFilter)DirectoryFileFilter.INSTANCE);
if(subdirs==null) return Collections.emptyList(); // shall never happen
for (File subdir : subdirs)
if(new File(subdir,"config.xml").exists()) {
String name = strategy.idFromFilename(subdir.getName());
User.getOrCreate(name, name, true);
}
lastScanned = System.currentTimeMillis();
}
byNameLock.readLock().lock();
ArrayList<User> r;
try {
r = new ArrayList<User>(byName.values());
r = new ArrayList<User>(AllUsers.byName().values());
} finally {
byNameLock.readLock().unlock();
}
@@ -578,27 +559,32 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
}
/**
* Reloads the configuration from disk.
* To be called from {@link Jenkins#reload} only.
*/
@Restricted(NoExternalUse.class)
public static void reload() {
byNameLock.readLock().lock();
try {
for (User u : byName.values()) {
u.load();
}
AllUsers.byName().clear();
} finally {
byNameLock.readLock().unlock();
UserDetailsCache.get().invalidateAll();
}
UserDetailsCache.get().invalidateAll();
AllUsers.scanAll();
}
/**
* Stop gap hack. Don't use it. To be removed in the trunk.
* @deprecated Used to be called by test harnesses; now ignored in that case.
*/
@Deprecated
public static void clear() {
if (ExtensionList.lookup(AllUsers.class).isEmpty()) {
// Historically this was called by JenkinsRule prior to startup. Ignore!
return;
}
byNameLock.writeLock().lock();
try {
byName.clear();
AllUsers.byName().clear();
} finally {
byNameLock.writeLock().unlock();
}
@@ -612,6 +598,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
final IdStrategy strategy = idStrategy();
byNameLock.writeLock().lock();
try {
ConcurrentMap<String, User> byName = AllUsers.byName();
for (Map.Entry<String, User> e : byName.entrySet()) {
String idkey = strategy.keyFor(e.getValue().id);
if (!idkey.equals(e.getKey())) {
@@ -748,6 +735,19 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
SaveableListener.fireOnChange(this, getConfigFile());
}
private Object writeReplace() {
return XmlFile.replaceIfNotAtTopLevel(this, () -> new Replacer(this));
}
private static class Replacer {
private final String id;
Replacer(User u) {
id = u.getId();
}
private Object readResolve() {
return getById(id, false);
}
}
/**
* Deletes the data directory and removes this user from Hudson.
*
@@ -758,7 +758,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
final IdStrategy strategy = idStrategy();
byNameLock.readLock().lock();
try {
byName.remove(strategy.keyFor(id));
AllUsers.byName().remove(strategy.keyFor(id));
} finally {
byNameLock.readLock().unlock();
}
@@ -865,16 +865,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
}
/**
* Keyed by {@link User#id}. This map is used to ensure
* singleton-per-id semantics of {@link User} objects.
*
* The key needs to be generated by {@link IdStrategy#keyFor(String)}.
*/
@GuardedBy("byNameLock")
private static final ConcurrentMap<String,User> byName = new ConcurrentHashMap<String, User>();
/**
* This lock is used to guard access to the {@link #byName} map. Use
* This lock is used to guard access to the {@link AllUsers#byName} map. Use
* {@link java.util.concurrent.locks.ReadWriteLock#readLock()} for normal access and
* {@link java.util.concurrent.locks.ReadWriteLock#writeLock()} for {@link #rekey()} or any other operation
* that requires operating on the map as a whole.
@@ -903,14 +894,6 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
};
}
public void checkPermission(Permission permission) {
getACL().checkPermission(permission);
}
public boolean hasPermission(Permission permission) {
return getACL().hasPermission(permission);
}
/**
* With ADMINISTER permission, can delete users with persisted data but can't delete self.
*/
@@ -1013,6 +996,45 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
return res;
}
/** Per-{@link Jenkins} holder of all known {@link User}s. */
@Extension
@Restricted(NoExternalUse.class)
public static final class AllUsers {
@Initializer(after = InitMilestone.JOB_LOADED) // so Jenkins.loadConfig has been called
public static void scanAll() {
IdStrategy strategy = idStrategy();
File[] subdirs = getRootDir().listFiles((FileFilter) DirectoryFileFilter.INSTANCE);
if (subdirs != null) {
for (File subdir : subdirs) {
if (new File(subdir, "config.xml").exists()) {
String name = strategy.idFromFilename(subdir.getName());
getOrCreate(name, /* <init> calls load(), probably clobbering this anyway */name, true);
}
}
}
}
@GuardedBy("User.byNameLock")
private final ConcurrentMap<String,User> byName = new ConcurrentHashMap<String, User>();
/**
* Keyed by {@link User#id}. This map is used to ensure
* singleton-per-id semantics of {@link User} objects.
*
* The key needs to be generated by {@link IdStrategy#keyFor(String)}.
*/
@GuardedBy("User.byNameLock")
static ConcurrentMap<String,User> byName() {
ExtensionList<AllUsers> instances = ExtensionList.lookup(AllUsers.class);
if (instances.size() != 1) {
throw new IllegalStateException();
}
return instances.get(0).byName;
}
}
public static abstract class CanonicalIdResolver extends AbstractDescribableImpl<CanonicalIdResolver> implements ExtensionPoint, Comparable<CanonicalIdResolver> {
/**
+4 -8
View File
@@ -579,14 +579,6 @@ public abstract class View extends AbstractModelObject implements AccessControll
return Jenkins.getInstance().getAuthorizationStrategy().getACL(this);
}
public void checkPermission(Permission p) {
getACL().checkPermission(p);
}
public boolean hasPermission(Permission p) {
return getACL().hasPermission(p);
}
/** @deprecated Does not work properly with moved jobs. Use {@link ItemListener#onLocationChanged} instead. */
@Deprecated
public void onJobRenamed(Item item, String oldName, String newName) {}
@@ -1053,6 +1045,10 @@ public abstract class View extends AbstractModelObject implements AccessControll
*/
@Restricted(DoNotUse.class)
public Categories doItemCategories(StaplerRequest req, StaplerResponse rsp, @QueryParameter String iconStyle) throws IOException, ServletException {
rsp.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
rsp.addHeader("Pragma", "no-cache");
rsp.addHeader("Expires", "0");
getOwner().checkPermission(Item.CREATE);
Categories categories = new Categories();
int order = 0;
@@ -64,7 +64,7 @@ public class ItemListener implements ExtensionPoint {
* @param src the item being copied
* @param parent the proposed parent
* @throws Failure to veto the operation.
* @since TODO
* @since 2.51
*/
public void onCheckCopy(Item src, ItemGroup parent) throws Failure {
}
@@ -200,7 +200,7 @@ public class ItemListener implements ExtensionPoint {
* @param src the item being copied
* @param parent the proposed parent
* @throws Failure if the copy operation has been vetoed.
* @since TODO
* @since 2.51
*/
public static void checkBeforeCopy(final Item src, final ItemGroup parent) throws Failure {
for (ItemListener l : all()) {
@@ -65,7 +65,7 @@ public class Tasks {
* @param t the {@link SubTask}.
* @return the {@link hudson.model.Item} associated with the {@link SubTask} or {@code null} if this
* {@link SubTask} is not associated with an {@link hudson.model.Item}
* @since TODO
* @since 2.55
*/
@CheckForNull
public static hudson.model.Item getItemOf(@Nonnull SubTask t) {
@@ -23,7 +23,6 @@
*/
package hudson.node_monitors;
import hudson.Util;
import hudson.Extension;
import hudson.model.Computer;
import hudson.remoting.Callable;
@@ -49,6 +48,9 @@ public class ResponseTimeMonitor extends NodeMonitor {
public static final AbstractNodeMonitorDescriptor<Data> DESCRIPTOR = new AbstractAsyncNodeMonitorDescriptor<Data>() {
@Override
protected Callable<Data,IOException> createCallable(Computer c) {
if (c.getChannel() == null) {
return null;
}
return new Step1(get(c));
}
@@ -328,7 +328,7 @@ public final class CronTab {
* This method modifies the given calendar and returns the same object.
*
* @throws RareOrImpossibleDateException if the date isn't hit in the 2 years after it indicates an impossible
* (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in TODO
* (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in 2.49
*/
public Calendar ceil(Calendar cal) {
Calendar twoYearsFuture = (Calendar) cal.clone();
@@ -389,7 +389,7 @@ public final class CronTab {
* This method modifies the given calendar and returns the same object.
*
* @throws RareOrImpossibleDateException if the date isn't hit in the 2 years before it indicates an impossible
* (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in TODO
* (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in 2.49
*/
public Calendar floor(Calendar cal) {
Calendar twoYearsAgo = (Calendar) cal.clone();
@@ -537,7 +537,7 @@ public final class CronTab {
* Returns the configured time zone, or null if none is configured
*
* @return the configured time zone, or null if none is configured
* @since TODO
* @since 2.54
*/
@CheckForNull public TimeZone getTimeZone() {
if (this.specTimezone == null) {
+4 -1
View File
@@ -527,7 +527,7 @@ public abstract class SCM implements Describable<SCM>, ExtensionPoint {
* are going to provide information about check out (like SVN revision number that was checked out), be prepared
* for the possibility that the check out hasn't happened yet.
*
* @since FIXME
* @since 2.60
*/
public void buildEnvironment(@Nonnull Run<?,?> build, @Nonnull Map<String,String> env) {
if (build instanceof AbstractBuild) {
@@ -535,6 +535,9 @@ public abstract class SCM implements Describable<SCM>, ExtensionPoint {
}
}
/**
* @deprecated in favor of {@link #buildEnvironment(Run, Map)}.
*/
@Deprecated
public void buildEnvVars(AbstractBuild<?,?> build, Map<String, String> env) {
if (Util.isOverridden(SCM.class, getClass(), "buildEnvironment", Run.class, Map.class)) {
@@ -42,11 +42,15 @@ public interface AccessControlled {
/**
* Convenient short-cut for {@code getACL().checkPermission(permission)}
*/
void checkPermission(@Nonnull Permission permission) throws AccessDeniedException;
default void checkPermission(@Nonnull Permission permission) throws AccessDeniedException {
getACL().checkPermission(permission);
}
/**
* Convenient short-cut for {@code getACL().hasPermission(permission)}
*/
boolean hasPermission(@Nonnull Permission permission);
default boolean hasPermission(@Nonnull Permission permission) {
return getACL().hasPermission(permission);
}
}
@@ -1,777 +0,0 @@
// Copyright (c) 2006 Damien Miller <djm@mindrot.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package hudson.security; // repackaged from http://www.mindrot.org/files/jBCrypt/jBCrypt-0.4.zip (and public modifier removed)
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
/**
* BCrypt implements OpenBSD-style Blowfish password hashing using
* the scheme described in "A Future-Adaptable Password Scheme" by
* Niels Provos and David Mazieres.
* <p>
* This password hashing system tries to thwart off-line password
* cracking using a computationally-intensive hashing algorithm,
* based on Bruce Schneier's Blowfish cipher. The work factor of
* the algorithm is parameterised, so it can be increased as
* computers get faster.
* <p>
* Usage is really simple. To hash a password for the first time,
* call the hashpw method with a random salt, like this:
* <p>
* <code>
* String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); <br />
* </code>
* <p>
* To check whether a plaintext password matches one that has been
* hashed previously, use the checkpw method:
* <p>
* <code>
* if (BCrypt.checkpw(candidate_password, stored_hash))<br />
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It matches");<br />
* else<br />
* &nbsp;&nbsp;&nbsp;&nbsp;System.out.println("It does not match");<br />
* </code>
* <p>
* The gensalt() method takes an optional parameter (log_rounds)
* that determines the computational complexity of the hashing:
* <p>
* <code>
* String strong_salt = BCrypt.gensalt(10)<br />
* String stronger_salt = BCrypt.gensalt(12)<br />
* </code>
* <p>
* The amount of work increases exponentially (2**log_rounds), so
* each increment is twice as much work. The default log_rounds is
* 10, and the valid range is 4 to 30.
*
* @author Damien Miller
* @version 0.2
*/
class BCrypt {
// BCrypt parameters
private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
private static final int BCRYPT_SALT_LEN = 16;
// Blowfish parameters
private static final int BLOWFISH_NUM_ROUNDS = 16;
// Initial contents of key schedule
private static final int P_orig[] = {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b
};
private static final int S_orig[] = {
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
};
// bcrypt IV: "OrpheanBeholderScryDoubt". The C implementation calls
// this "ciphertext", but it is really plaintext or an IV. We keep
// the name to make code comparison easier.
static private final int bf_crypt_ciphertext[] = {
0x4f727068, 0x65616e42, 0x65686f6c,
0x64657253, 0x63727944, 0x6f756274
};
// Table for Base64 encoding
static private final char base64_code[] = {
'.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9'
};
// Table for Base64 decoding
static private final byte index_64[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 0, 1, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
-1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-1, -1, -1, -1, -1, -1, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, -1, -1, -1, -1, -1
};
// Expanded Blowfish key
private int P[];
private int S[];
/**
* Encode a byte array using bcrypt's slightly-modified base64
* encoding scheme. Note that this is *not* compatible with
* the standard MIME-base64 encoding.
*
* @param d the byte array to encode
* @param len the number of bytes to encode
* @return base64-encoded string
* @exception IllegalArgumentException if the length is invalid
*/
private static String encode_base64(byte d[], int len)
throws IllegalArgumentException {
int off = 0;
StringBuffer rs = new StringBuffer();
int c1, c2;
if (len <= 0 || len > d.length)
throw new IllegalArgumentException ("Invalid len");
while (off < len) {
c1 = d[off++] & 0xff;
rs.append(base64_code[(c1 >> 2) & 0x3f]);
c1 = (c1 & 0x03) << 4;
if (off >= len) {
rs.append(base64_code[c1 & 0x3f]);
break;
}
c2 = d[off++] & 0xff;
c1 |= (c2 >> 4) & 0x0f;
rs.append(base64_code[c1 & 0x3f]);
c1 = (c2 & 0x0f) << 2;
if (off >= len) {
rs.append(base64_code[c1 & 0x3f]);
break;
}
c2 = d[off++] & 0xff;
c1 |= (c2 >> 6) & 0x03;
rs.append(base64_code[c1 & 0x3f]);
rs.append(base64_code[c2 & 0x3f]);
}
return rs.toString();
}
/**
* Look up the 3 bits base64-encoded by the specified character,
* range-checking againt conversion table
* @param x the base64-encoded value
* @return the decoded value of x
*/
private static byte char64(char x) {
if ((int)x < 0 || (int)x > index_64.length)
return -1;
return index_64[(int)x];
}
/**
* Decode a string encoded using bcrypt's base64 scheme to a
* byte array. Note that this is *not* compatible with
* the standard MIME-base64 encoding.
* @param s the string to decode
* @param maxolen the maximum number of bytes to decode
* @return an array containing the decoded bytes
* @throws IllegalArgumentException if maxolen is invalid
*/
private static byte[] decode_base64(String s, int maxolen)
throws IllegalArgumentException {
StringBuffer rs = new StringBuffer();
int off = 0, slen = s.length(), olen = 0;
byte ret[];
byte c1, c2, c3, c4, o;
if (maxolen <= 0)
throw new IllegalArgumentException ("Invalid maxolen");
while (off < slen - 1 && olen < maxolen) {
c1 = char64(s.charAt(off++));
c2 = char64(s.charAt(off++));
if (c1 == -1 || c2 == -1)
break;
o = (byte)(c1 << 2);
o |= (c2 & 0x30) >> 4;
rs.append((char)o);
if (++olen >= maxolen || off >= slen)
break;
c3 = char64(s.charAt(off++));
if (c3 == -1)
break;
o = (byte)((c2 & 0x0f) << 4);
o |= (c3 & 0x3c) >> 2;
rs.append((char)o);
if (++olen >= maxolen || off >= slen)
break;
c4 = char64(s.charAt(off++));
o = (byte)((c3 & 0x03) << 6);
o |= c4;
rs.append((char)o);
++olen;
}
ret = new byte[olen];
for (off = 0; off < olen; off++)
ret[off] = (byte)rs.charAt(off);
return ret;
}
/**
* Blowfish encipher a single 64-bit block encoded as
* two 32-bit halves
* @param lr an array containing the two 32-bit half blocks
* @param off the position in the array of the blocks
*/
private final void encipher(int lr[], int off) {
int i, n, l = lr[off], r = lr[off + 1];
l ^= P[0];
for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) {
// Feistel substitution on left word
n = S[(l >> 24) & 0xff];
n += S[0x100 | ((l >> 16) & 0xff)];
n ^= S[0x200 | ((l >> 8) & 0xff)];
n += S[0x300 | (l & 0xff)];
r ^= n ^ P[++i];
// Feistel substitution on right word
n = S[(r >> 24) & 0xff];
n += S[0x100 | ((r >> 16) & 0xff)];
n ^= S[0x200 | ((r >> 8) & 0xff)];
n += S[0x300 | (r & 0xff)];
l ^= n ^ P[++i];
}
lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
lr[off + 1] = l;
}
/**
* Cycically extract a word of key material
* @param data the string to extract the data from
* @param offp a "pointer" (as a one-entry array) to the
* current offset into data
* @return the next word of material from data
*/
private static int streamtoword(byte data[], int offp[]) {
int i;
int word = 0;
int off = offp[0];
for (i = 0; i < 4; i++) {
word = (word << 8) | (data[off] & 0xff);
off = (off + 1) % data.length;
}
offp[0] = off;
return word;
}
/**
* Initialise the Blowfish key schedule
*/
private void init_key() {
P = (int[])P_orig.clone();
S = (int[])S_orig.clone();
}
/**
* Key the Blowfish cipher
* @param key an array containing the key
*/
private void key(byte key[]) {
int i;
int koffp[] = { 0 };
int lr[] = { 0, 0 };
int plen = P.length, slen = S.length;
for (i = 0; i < plen; i++)
P[i] = P[i] ^ streamtoword(key, koffp);
for (i = 0; i < plen; i += 2) {
encipher(lr, 0);
P[i] = lr[0];
P[i + 1] = lr[1];
}
for (i = 0; i < slen; i += 2) {
encipher(lr, 0);
S[i] = lr[0];
S[i + 1] = lr[1];
}
}
/**
* Perform the "enhanced key schedule" step described by
* Provos and Mazieres in "A Future-Adaptable Password Scheme"
* http://www.openbsd.org/papers/bcrypt-paper.ps
* @param data salt information
* @param key password information
*/
private void ekskey(byte data[], byte key[]) {
int i;
int koffp[] = { 0 }, doffp[] = { 0 };
int lr[] = { 0, 0 };
int plen = P.length, slen = S.length;
for (i = 0; i < plen; i++)
P[i] = P[i] ^ streamtoword(key, koffp);
for (i = 0; i < plen; i += 2) {
lr[0] ^= streamtoword(data, doffp);
lr[1] ^= streamtoword(data, doffp);
encipher(lr, 0);
P[i] = lr[0];
P[i + 1] = lr[1];
}
for (i = 0; i < slen; i += 2) {
lr[0] ^= streamtoword(data, doffp);
lr[1] ^= streamtoword(data, doffp);
encipher(lr, 0);
S[i] = lr[0];
S[i + 1] = lr[1];
}
}
/**
* Perform the central password hashing step in the
* bcrypt scheme
* @param password the password to hash
* @param salt the binary salt to hash with the password
* @param log_rounds the binary logarithm of the number
* of rounds of hashing to apply
* @param cdata the plaintext to encrypt
* @return an array containing the binary hashed password
*/
public byte[] crypt_raw(byte password[], byte salt[], int log_rounds,
int cdata[]) {
int rounds, i, j;
int clen = cdata.length;
byte ret[];
if (log_rounds < 4 || log_rounds > 30)
throw new IllegalArgumentException ("Bad number of rounds");
rounds = 1 << log_rounds;
if (salt.length != BCRYPT_SALT_LEN)
throw new IllegalArgumentException ("Bad salt length");
init_key();
ekskey(salt, password);
for (i = 0; i != rounds; i++) {
key(password);
key(salt);
}
for (i = 0; i < 64; i++) {
for (j = 0; j < (clen >> 1); j++)
encipher(cdata, j << 1);
}
ret = new byte[clen * 4];
for (i = 0, j = 0; i < clen; i++) {
ret[j++] = (byte)((cdata[i] >> 24) & 0xff);
ret[j++] = (byte)((cdata[i] >> 16) & 0xff);
ret[j++] = (byte)((cdata[i] >> 8) & 0xff);
ret[j++] = (byte)(cdata[i] & 0xff);
}
return ret;
}
/**
* Hash a password using the OpenBSD bcrypt scheme
* @param password the password to hash
* @param salt the salt to hash with (perhaps generated
* using BCrypt.gensalt)
* @return the hashed password
*/
public static String hashpw(String password, String salt) {
BCrypt B;
String real_salt;
byte passwordb[], saltb[], hashed[];
char minor = (char)0;
int rounds, off = 0;
StringBuffer rs = new StringBuffer();
if (salt.charAt(0) != '$' || salt.charAt(1) != '2')
throw new IllegalArgumentException ("Invalid salt version");
if (salt.charAt(2) == '$')
off = 3;
else {
minor = salt.charAt(2);
if (minor != 'a' || salt.charAt(3) != '$')
throw new IllegalArgumentException ("Invalid salt revision");
off = 4;
}
// Extract number of rounds
if (salt.charAt(off + 2) > '$')
throw new IllegalArgumentException ("Missing salt rounds");
rounds = Integer.parseInt(salt.substring(off, off + 2));
real_salt = salt.substring(off + 3, off + 25);
try {
passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
throw new AssertionError("UTF-8 is not supported");
}
saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
B = new BCrypt();
hashed = B.crypt_raw(passwordb, saltb, rounds,
(int[])bf_crypt_ciphertext.clone());
rs.append("$2");
if (minor >= 'a')
rs.append(minor);
rs.append("$");
if (rounds < 10)
rs.append("0");
if (rounds > 30) {
throw new IllegalArgumentException(
"rounds exceeds maximum (30)");
}
rs.append(Integer.toString(rounds));
rs.append("$");
rs.append(encode_base64(saltb, saltb.length));
rs.append(encode_base64(hashed,
bf_crypt_ciphertext.length * 4 - 1));
return rs.toString();
}
/**
* Generate a salt for use with the BCrypt.hashpw() method
* @param log_rounds the log2 of the number of rounds of
* hashing to apply - the work factor therefore increases as
* 2**log_rounds.
* @param random an instance of SecureRandom to use
* @return an encoded salt value
*/
public static String gensalt(int log_rounds, SecureRandom random) {
StringBuffer rs = new StringBuffer();
byte rnd[] = new byte[BCRYPT_SALT_LEN];
random.nextBytes(rnd);
rs.append("$2a$");
if (log_rounds < 10)
rs.append("0");
if (log_rounds > 30) {
throw new IllegalArgumentException(
"log_rounds exceeds maximum (30)");
}
rs.append(Integer.toString(log_rounds));
rs.append("$");
rs.append(encode_base64(rnd, rnd.length));
return rs.toString();
}
/**
* Generate a salt for use with the BCrypt.hashpw() method
* @param log_rounds the log2 of the number of rounds of
* hashing to apply - the work factor therefore increases as
* 2**log_rounds.
* @return an encoded salt value
*/
public static String gensalt(int log_rounds) {
return gensalt(log_rounds, new SecureRandom());
}
/**
* Generate a salt for use with the BCrypt.hashpw() method,
* selecting a reasonable default for the number of hashing
* rounds to apply
* @return an encoded salt value
*/
public static String gensalt() {
return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS);
}
/**
* Check that a plaintext password matches a previously hashed
* one
* @param plaintext the plaintext password to verify
* @param hashed the previously-hashed password
* @return true if the passwords match, false otherwise
*/
public static boolean checkpw(String plaintext, String hashed) {
byte hashed_bytes[];
byte try_bytes[];
try {
String try_pw = hashpw(plaintext, hashed);
hashed_bytes = hashed.getBytes("UTF-8");
try_bytes = try_pw.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
return false;
}
if (hashed_bytes.length != try_bytes.length)
return false;
byte ret = 0;
for (int i = 0; i < try_bytes.length; i++)
ret |= hashed_bytes[i] ^ try_bytes[i];
return ret == 0;
}
}
@@ -61,6 +61,7 @@ import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.dao.DataAccessException;
import javax.servlet.Filter;
+2 -10
View File
@@ -80,7 +80,7 @@ import java.util.concurrent.Future;
*
* <h3>Views</h3>
*
* Since version TODO, Jenkins clouds are visualized in UI. Implementations can provide <tt>top</tt> or <tt>main</tt> view
* Since version 2.64, Jenkins clouds are visualized in UI. Implementations can provide <tt>top</tt> or <tt>main</tt> view
* to be presented at the top of the page or at the bottom respectively. In the middle, actions have their <tt>summary</tt>
* views displayed. Actions further contribute to <tt>sidepanel</tt> with <tt>box</tt> views. All mentioned views are
* optional to preserve backward compatibility.
@@ -110,7 +110,7 @@ public abstract class Cloud extends Actionable implements ExtensionPoint, Descri
/**
* Get URL of the cloud.
*
* @since TODO
* @since 2.64
* @return Jenkins relative URL.
*/
public @Nonnull String getUrl() {
@@ -128,14 +128,6 @@ public abstract class Cloud extends Actionable implements ExtensionPoint, Descri
return Jenkins.getInstance().getAuthorizationStrategy().getACL(this);
}
public final void checkPermission(Permission permission) {
getACL().checkPermission(permission);
}
public final boolean hasPermission(Permission permission) {
return getACL().hasPermission(permission);
}
/**
* Provisions new {@link Node}s from this cloud.
*
@@ -48,7 +48,7 @@ import org.apache.tools.ant.util.DeweyDecimal;
* </dl>
*
* @author Stephen Connolly
* @since 24-Apr-2008 22:12:35
* @since 1.216-ish
* @see ComputerConnector
*/
public abstract class ComputerLauncher extends AbstractDescribableImpl<ComputerLauncher> implements ExtensionPoint {
@@ -25,13 +25,17 @@ package hudson.slaves;
import hudson.Extension;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Descriptor;
import hudson.model.DescriptorVisibilityFilter;
import hudson.model.TaskListener;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import jenkins.slaves.RemotingWorkDirSettings;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;
/**
@@ -52,24 +56,72 @@ public class JNLPLauncher extends ComputerLauncher {
*
* @since 1.250
*/
@CheckForNull
public final String tunnel;
/**
* Additional JVM arguments. Can be null.
* @since 1.297
*/
@CheckForNull
public final String vmargs;
@Nonnull
private RemotingWorkDirSettings workDirSettings;
@DataBoundConstructor
public JNLPLauncher(String tunnel, String vmargs) {
public JNLPLauncher(@CheckForNull String tunnel, @CheckForNull String vmargs, @Nonnull RemotingWorkDirSettings workDirSettings) {
this.tunnel = Util.fixEmptyAndTrim(tunnel);
this.vmargs = Util.fixEmptyAndTrim(vmargs);
this.workDirSettings = workDirSettings;
}
@Deprecated
public JNLPLauncher(String tunnel, String vmargs) {
// TODO: Enable workDir by default in API? Otherwise classes inheriting from JNLPLauncher
// will need to enable the feature by default as well.
// https://github.com/search?q=org%3Ajenkinsci+%22extends+JNLPLauncher%22&type=Code
this(tunnel, vmargs, RemotingWorkDirSettings.getDisabledDefaults());
}
/**
* @deprecated This Launcher does not enable the work directory.
* It is recommended to use {@link #JNLPLauncher(boolean)}
*/
@Deprecated
public JNLPLauncher() {
this(null,null);
this(false);
}
/**
* Constructor with default options.
*
* @param enableWorkDir If {@code true}, the work directory will be enabled with default settings.
*/
public JNLPLauncher(boolean enableWorkDir) {
this(null, null, enableWorkDir
? RemotingWorkDirSettings.getEnabledDefaults()
: RemotingWorkDirSettings.getDisabledDefaults());
}
protected Object readResolve() {
if (workDirSettings == null) {
// For the migrated code agents are always disabled
workDirSettings = RemotingWorkDirSettings.getDisabledDefaults();
}
return this;
}
/**
* Returns work directory settings.
*
* @since TODO
*/
@Nonnull
public RemotingWorkDirSettings getWorkDirSettings() {
return workDirSettings;
}
@Override
public boolean isLaunchSupported() {
return false;
@@ -86,6 +138,22 @@ public class JNLPLauncher extends ComputerLauncher {
*/
public static /*almost final*/ Descriptor<ComputerLauncher> DESCRIPTOR;
/**
* Gets work directory options as a String.
*
* In public API {@code getWorkDirSettings().toCommandLineArgs(computer)} should be used instead
* @param computer Computer
* @return Command line options for launching with the WorkDir
*/
@Nonnull
@Restricted(NoExternalUse.class)
public String getWorkDirOptions(@Nonnull Computer computer) {
if(!(computer instanceof SlaveComputer)) {
return "";
}
return workDirSettings.toCommandLineString((SlaveComputer)computer);
}
@Extension @Symbol("jnlp")
public static class DescriptorImpl extends Descriptor<ComputerLauncher> {
public DescriptorImpl() {
@@ -95,6 +163,22 @@ public class JNLPLauncher extends ComputerLauncher {
public String getDisplayName() {
return Messages.JNLPLauncher_displayName();
}
/**
* Checks if Work Dir settings should be displayed.
*
* This flag is checked in {@code config.jelly} before displaying the
* {@link JNLPLauncher#workDirSettings} property.
* By default the configuration is displayed only for {@link JNLPLauncher},
* but the implementation can be overridden.
* @return {@code true} if work directories are supported by the launcher type.
* @since TODO
*/
public boolean isWorkDirSupported() {
// This property is included only for JNLPLauncher by default.
// Causes JENKINS-45895 in the case of includes otherwise
return DescriptorImpl.class.equals(getClass());
}
};
/**
@@ -454,6 +454,9 @@ public class SlaveComputer extends Computer {
}
@Override public Integer call() {
Channel c = Channel.current();
if (c == null) {
return -1;
}
return resource ? c.resourceLoadingCount.get() : c.classLoadingCount.get();
}
}
@@ -471,6 +474,9 @@ public class SlaveComputer extends Computer {
}
@Override public Long call() {
Channel c = Channel.current();
if (c == null) {
return Long.valueOf(-1);
}
return resource ? c.resourceLoadingTime.get() : c.classLoadingTime.get();
}
}
@@ -33,8 +33,8 @@ import java.io.ObjectStreamException;
/**
* Installs tool via script execution of Batch script.
* Inspired by "Command installer" from the Jenkins core.
* @since 0.1
*
* @since 1.549
*/
public class BatchCommandInstaller extends AbstractCommandInstaller {
@@ -38,6 +38,7 @@ import java.io.Serializable;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import javax.annotation.Nonnull;
/**
* Used to build up arguments for a process invocation.
@@ -132,6 +133,16 @@ public class ArgumentListBuilder implements Serializable, Cloneable {
}
return this;
}
/**
* @since TODO
*/
public ArgumentListBuilder add(@Nonnull Iterable<String> args) {
for (String arg : args) {
add(arg);
}
return this;
}
/**
* Decomposes the given token into multiple arguments by splitting via whitespace.
@@ -45,7 +45,7 @@ import java.util.List;
* Collection whose change is notified to the parent object for persistence.
*
* @author Kohsuke Kawaguchi
* @since 1.MULTISOURCE
* @since 1.333
*/
public class PersistedList<T> extends AbstractList<T> {
protected final CopyOnWriteList<T> data = new CopyOnWriteList<T>();
@@ -1,11 +1,10 @@
package hudson.util;
import org.apache.commons.codec.binary.Base64;
import java.io.DataInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
/**
* Filter InputStream that decodes base64 without doing any buffering.
@@ -22,6 +21,7 @@ public class UnbufferedBase64InputStream extends FilterInputStream {
private byte[] decoded;
private int pos;
private final DataInputStream din;
private static final Base64.Decoder decoder = Base64.getMimeDecoder();
public UnbufferedBase64InputStream(InputStream in) {
super(in);
@@ -38,7 +38,7 @@ public class UnbufferedBase64InputStream extends FilterInputStream {
if (pos==decoded.length) {
din.readFully(encoded);
decoded = Base64.decodeBase64(encoded);
decoded = decoder.decode(encoded);
if (decoded.length==0) return -1; // EOF
pos = 0;
}
@@ -8,6 +8,8 @@ import hudson.TcpSlaveAgentListener;
import java.io.IOException;
import java.net.Socket;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
/**
@@ -18,6 +20,15 @@ import jenkins.model.Jenkins;
* Implementations of this extension point is singleton, and its {@link #handle(Socket)} method
* gets invoked concurrently whenever a new connection comes in.
*
* <h2>Extending UI</h2>
* <dl>
* <dt>description.jelly</dt>
* <dd>Optional protocol description</dd>
* <dt>deprecationCause.jelly</dt>
* <dd>Optional. If the protocol is marked as {@link #isDeprecated()},
* clarifies the deprecation reason and provides extra documentation links</dd>
* </dl>
*
* @author Kohsuke Kawaguchi
* @since 1.467
* @see TcpSlaveAgentListener
@@ -53,6 +64,16 @@ public abstract class AgentProtocol implements ExtensionPoint {
public boolean isRequired() {
return false;
}
/**
* Checks if the protocol is deprecated.
*
* @since TODO
*/
public boolean isDeprecated() {
return false;
}
/**
* Protocol name.
*
@@ -86,6 +107,7 @@ public abstract class AgentProtocol implements ExtensionPoint {
return ExtensionList.lookup(AgentProtocol.class);
}
@CheckForNull
public static AgentProtocol of(String protocolName) {
for (AgentProtocol p : all()) {
String n = p.getName();
@@ -23,7 +23,7 @@ import java.io.File;
*
* @author Kohsuke Kawaguchi
* @see FilePath
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class FilePathFilter {
/**
@@ -15,7 +15,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*
* @author Kohsuke Kawaguchi
* @see FilePath
* @since 1.THU
* @since 1.587 / 1.580.1
*/
class FilePathFilterAggregator extends FilePathFilter {
private final CopyOnWriteArrayList<Entry> all = new CopyOnWriteArrayList<Entry>();
@@ -7,7 +7,7 @@ import org.jenkinsci.remoting.RoleChecker;
/**
* {@link FileCallable}s that are meant to be only used on the master.
*
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class MasterToSlaveFileCallable<T> implements FileCallable<T> {
@Override
@@ -7,7 +7,7 @@ import java.io.File;
* operations as a single string argument.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class ReflectiveFilePathFilter extends FilePathFilter {
/**
@@ -7,7 +7,7 @@ import org.jenkinsci.remoting.RoleChecker;
/**
* {@link FileCallable}s that can be executed on the master, sent by the agent.
*
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class SlaveToMasterFileCallable<T> implements FileCallable<T> {
@Override
@@ -52,6 +52,8 @@ import java.net.HttpRetryException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import jenkins.CLI;
@@ -62,6 +64,7 @@ import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.jenkinsci.remoting.engine.JnlpProtocol4Handler;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.stapler.interceptor.RequirePOST;
@@ -127,6 +130,13 @@ public class SetupWizard extends PageDecorator {
// Disable CLI over Remoting
CLI.get().setEnabled(false);
// Disable old Non-Encrypted protocols ()
HashSet<String> newProtocols = new HashSet<>(jenkins.getAgentProtocols());
newProtocols.removeAll(Arrays.asList(
"JNLP2-connect", "JNLP-connect", "CLI-connect"
));
jenkins.setAgentProtocols(newProtocols);
// require a crumb issuer
jenkins.setCrumbIssuer(new DefaultCrumbIssuer(false));
+17 -25
View File
@@ -251,7 +251,6 @@ 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;
@@ -903,26 +902,10 @@ 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);
}
try {
ClassFilter.appendDefaultFilter(Pattern.compile("java[.]security[.]SignedObject")); // TODO move to standard blacklist
} catch (ClassFilter.ClassFilterException ex) {
throw new IOException("Remoting library rejected the java[.]security[.]SignedObject blacklist pattern", ex);
}
// initialization consists of ...
@@ -2176,7 +2159,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
/**
* Returns the enabled and activated administrative monitors.
* @since TODO
* @since 2.64
*/
public List<AdministrativeMonitor> getActiveAdministrativeMonitors() {
return administrativeMonitors.stream().filter(m -> m.isEnabled() && m.isActivated()).collect(Collectors.toList());
@@ -2326,12 +2309,21 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
* It is done in this order so that it can work correctly even in the face
* of a reverse proxy.
*
* @return null if this parameter is not configured by the user and the calling thread is not in an HTTP request; otherwise the returned URL will always have the trailing {@code /}
* @return {@code null} if this parameter is not configured by the user and the calling thread is not in an HTTP request;
* otherwise the returned URL will always have the trailing {@code /}
* @throws IllegalStateException {@link JenkinsLocationConfiguration} cannot be retrieved.
* Jenkins instance may be not ready, or there is an extension loading glitch.
* @since 1.66
* @see <a href="https://wiki.jenkins-ci.org/display/JENKINS/Hyperlinks+in+HTML">Hyperlinks in HTML</a>
*/
public @Nullable String getRootUrl() {
String url = JenkinsLocationConfiguration.get().getUrl();
public @Nullable String getRootUrl() throws IllegalStateException {
final JenkinsLocationConfiguration config = JenkinsLocationConfiguration.get();
if (config == null) {
// Try to get standard message if possible
final Jenkins j = Jenkins.getInstance();
throw new IllegalStateException("Jenkins instance " + j + " has been successfully initialized, but JenkinsLocationConfiguration is undefined.");
}
String url = config.getUrl();
if(url!=null) {
return Util.ensureEndsWith(url,"/");
}
@@ -41,6 +41,12 @@ public class JenkinsLocationConfiguration extends GlobalConfiguration {
// just to suppress warnings
private transient String charset,useSsl;
/**
* Gets local configuration.
*
* @return {@code null} if the {@link GlobalConfiguration#all()} list does not contain this extension.
* Most likely it means that the Jenkins instance has not been fully loaded yet.
*/
public static @CheckForNull JenkinsLocationConfiguration get() {
return GlobalConfiguration.all().get(JenkinsLocationConfiguration.class);
}
@@ -29,6 +29,7 @@ import hudson.model.Run;
/**
* Optional interface for {@link Action}s that add themselves to a {@link Run}.
* You may keep a {@code transient} reference to an owning build, restored in {@link #onLoad}.
* @since 1.519, 1.509.3
*/
public interface RunAction2 extends Action {
@@ -41,7 +41,7 @@ import javax.annotation.concurrent.GuardedBy;
/**
* A {@link Queue.QueueDecisionHandler} that blocks items being deleted from entering the queue.
*
* @since TODO
* @since 2.55
*/
@Extension
public class ItemDeletion extends Queue.QueueDecisionHandler {
@@ -48,7 +48,7 @@ import java.util.logging.Logger;
/**
* Allows a {@link Run} to provide {@link SCM}-related methods, such as providing changesets and culprits.
*
* @since FIXME
* @since 2.60
*/
public interface RunWithSCM<JobT extends Job<JobT, RunT>,
RunT extends Run<JobT, RunT> & RunWithSCM<JobT,RunT>> {
@@ -13,7 +13,7 @@ import javax.annotation.Nullable;
* Intercepts the new creation of {@link Channel} and tweak its configuration.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class ChannelConfigurator implements ExtensionPoint {
/**
@@ -27,6 +27,7 @@ import java.util.Arrays;
*/
public class HMACConfidentialKey extends ConfidentialKey {
private volatile SecretKey key;
private Mac mac;
private final int length;
/**
@@ -61,12 +62,14 @@ public class HMACConfidentialKey extends ConfidentialKey {
this(owner,shortName,Integer.MAX_VALUE);
}
/**
* Computes the message authentication code for the specified byte sequence.
*/
public byte[] mac(byte[] message) {
return chop(createMac().doFinal(message));
public synchronized byte[] mac(byte[] message) {
if (mac == null) {
mac = createMac();
}
return chop(mac.doFinal(message));
}
/**
@@ -8,7 +8,7 @@ import org.jenkinsci.remoting.RoleChecker;
* Convenient {@link Callable} meant to be run on agent.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class MasterToSlaveCallable<V, T extends Throwable> implements Callable<V,T> {
@Override
@@ -8,7 +8,7 @@ import org.jenkinsci.remoting.RoleChecker;
* just as a convenient function that has parameterized return value and exception type.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class NotReallyRoleSensitiveCallable<V,T extends Throwable> implements Callable<V,T> {
@Override
@@ -12,7 +12,7 @@ import org.jenkinsci.remoting.Role;
* not have any role.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public class Roles {
/**
@@ -8,7 +8,7 @@ import org.jenkinsci.remoting.RoleChecker;
* Convenient {@link Callable} that are meant to run on the master (sent by agent/CLI/etc).
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class SlaveToMasterCallable<V, T extends Throwable> implements Callable<V,T> {
@Override
@@ -18,7 +18,7 @@ import java.io.IOException;
* Report any rejected {@link Callable}s and {@link FilePath} executions and allow
* admins to whitelist them.
*
* @since 1.THU
* @since 1.587 / 1.580.1
* @author Kohsuke Kawaguchi
*/
@Extension @Symbol("slaveToMasterAccessControl")
@@ -17,7 +17,7 @@ import java.io.File;
* This class is just a glue, and the real logic happens inside {@link AdminWhitelistRule}
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public class AdminFilePathFilter extends ReflectiveFilePathFilter {
@@ -22,7 +22,7 @@ import java.util.logging.Logger;
* Inspects {@link Callable}s that run on the master.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
@Restricted(NoExternalUse.class) // used implicitly via listener
public class CallableDirectionChecker extends RoleChecker {
@@ -18,7 +18,7 @@ import java.util.Collection;
* {@link Callable#checkRoles(RoleChecker)} method.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
public abstract class CallableWhitelist implements ExtensionPoint {
/**
@@ -12,7 +12,7 @@ import org.kohsuke.stapler.StaplerRequest;
* Exposes {@link AdminWhitelistRule#masterKillSwitch} to the admin.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
@Extension
public class MasterKillSwitchConfiguration extends GlobalConfiguration {
@@ -14,7 +14,7 @@ import java.io.IOException;
* If {@link AdminWhitelistRule#masterKillSwitch} is on, warn the user.
*
* @author Kohsuke Kawaguchi
* @since 1.THU
* @since 1.587 / 1.580.1
*/
@Extension
public class MasterKillSwitchWarning extends AdministrativeMonitor {
@@ -0,0 +1,113 @@
/*
* The MIT License
*
* Copyright (c) 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 jenkins.slaves;
import hudson.Extension;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.model.AdministrativeMonitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import jenkins.AgentProtocol;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Monitors enabled protocols and warns if an {@link AgentProtocol} is deprecated.
*
* @author Oleg Nenashev
* @since TODO
* @see AgentProtocol
*/
@Extension
@Symbol("deprecatedAgentProtocol")
@Restricted(NoExternalUse.class)
public class DeprecatedAgentProtocolMonitor extends AdministrativeMonitor {
private static final Logger LOGGER = Logger.getLogger(DeprecatedAgentProtocolMonitor.class.getName());
public DeprecatedAgentProtocolMonitor() {
super();
}
@Override
public String getDisplayName() {
return Messages.DeprecatedAgentProtocolMonitor_displayName();
}
@Override
public boolean isActivated() {
final Set<String> agentProtocols = Jenkins.getInstance().getAgentProtocols();
for (String name : agentProtocols) {
AgentProtocol pr = AgentProtocol.of(name);
if (pr != null && pr.isDeprecated()) {
return true;
}
}
return false;
}
@Restricted(NoExternalUse.class)
public String getDeprecatedProtocols() {
String res = getDeprecatedProtocolsString();
return res != null ? res : "N/A";
}
@CheckForNull
public static String getDeprecatedProtocolsString() {
final List<String> deprecatedProtocols = new ArrayList<>();
final Set<String> agentProtocols = Jenkins.getInstance().getAgentProtocols();
for (String name : agentProtocols) {
AgentProtocol pr = AgentProtocol.of(name);
if (pr != null && pr.isDeprecated()) {
deprecatedProtocols.add(name);
}
}
if (deprecatedProtocols.isEmpty()) {
return null;
}
return StringUtils.join(deprecatedProtocols, ',');
}
@Initializer(after = InitMilestone.JOB_LOADED)
@Restricted(NoExternalUse.class)
public static void initializerCheck() {
String protocols = getDeprecatedProtocolsString();
if(protocols != null) {
LOGGER.log(Level.WARNING, "This Jenkins instance uses deprecated Remoting protocols: {0}"
+ "It may impact stability of the instance. "
+ "If newer protocol versions are supported by all system components "
+ "(agents, CLI and other clients), "
+ "it is highly recommended to disable the deprecated protocols.", protocols);
}
}
}
@@ -79,6 +79,11 @@ public class JnlpSlaveAgentProtocol extends AgentProtocol {
return OPT_IN;
}
@Override
public boolean isDeprecated() {
return true;
}
@Override
public String getName() {
return handler.isEnabled() ? handler.getName() : null;
@@ -53,6 +53,11 @@ public class JnlpSlaveAgentProtocol2 extends AgentProtocol {
return false;
}
@Override
public boolean isDeprecated() {
return true;
}
/**
* {@inheritDoc}
*/
@@ -14,6 +14,7 @@ import javax.inject.Inject;
import jenkins.AgentProtocol;
import jenkins.model.Jenkins;
import jenkins.util.SystemProperties;
import org.jenkinsci.Symbol;
import org.jenkinsci.remoting.engine.JnlpClientDatabase;
import org.jenkinsci.remoting.engine.JnlpConnectionState;
import org.jenkinsci.remoting.engine.JnlpProtocol3Handler;
@@ -25,10 +26,11 @@ import org.kohsuke.accmod.restrictions.NoExternalUse;
*
* <p>@see {@link org.jenkinsci.remoting.engine.JnlpProtocol3Handler} for more details.
*
* @since 1.XXX
* @since 1.653
*/
@Deprecated
@Extension
@Symbol("jnlp3")
public class JnlpSlaveAgentProtocol3 extends AgentProtocol {
private NioChannelSelector hub;
@@ -65,6 +67,11 @@ public class JnlpSlaveAgentProtocol3 extends AgentProtocol {
return Messages.JnlpSlaveAgentProtocol3_displayName();
}
@Override
public boolean isDeprecated() {
return true;
}
@Override
public void handle(Socket socket) throws IOException, InterruptedException {
handler.handle(socket,
@@ -48,6 +48,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import jenkins.AgentProtocol;
import jenkins.model.identity.InstanceIdentityProvider;
import org.jenkinsci.Symbol;
import org.jenkinsci.remoting.engine.JnlpConnectionState;
import org.jenkinsci.remoting.engine.JnlpProtocol4Handler;
import org.jenkinsci.remoting.protocol.IOHub;
@@ -58,10 +59,11 @@ import org.jenkinsci.remoting.protocol.cert.PublicKeyMatchingX509ExtendedTrustMa
*
* <p>@see {@link org.jenkinsci.remoting.engine.JnlpProtocol4Handler} for more details.
*
* @since 2.27 available as the experimental protocol
* @since TODO enabled by default
* @since 2.27 available as experimental protocol
* @since 2.41 enabled by default
*/
@Extension
@Symbol("jnlp4")
public class JnlpSlaveAgentProtocol4 extends AgentProtocol {
/**
* Our logger.
@@ -0,0 +1,229 @@
/*
* The MIT License
*
* Copyright (c) 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 jenkins.slaves;
import hudson.Extension;
import hudson.Util;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.model.Slave;
import hudson.slaves.SlaveComputer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* Defines settings of the Remoting work directory.
*
* This class contains Remoting Work Directory settings, which can be used when starting Jenkins agents.
* See <a href="https://github.com/jenkinsci/remoting/blob/master/docs/workDir.md">Remoting Work Dir Documentation</a>.
*
* @author Oleg Nenashev
* @since TODO
*/
public class RemotingWorkDirSettings implements Describable<RemotingWorkDirSettings> {
private static final String DEFAULT_INTERNAL_DIR = "remoting";
private static final RemotingWorkDirSettings LEGACY_DEFAULT = new RemotingWorkDirSettings(true, null, DEFAULT_INTERNAL_DIR, false);
private static final RemotingWorkDirSettings ENABLED_DEFAULT = new RemotingWorkDirSettings(false, null, DEFAULT_INTERNAL_DIR, false);
private final boolean disabled;
@CheckForNull
private final String workDirPath;
@Nonnull
private final String internalDir;
private final boolean failIfWorkDirIsMissing;
@DataBoundConstructor
public RemotingWorkDirSettings(boolean disabled,
@CheckForNull String workDirPath, @CheckForNull String internalDir,
boolean failIfWorkDirIsMissing) {
this.disabled = disabled;
this.workDirPath = Util.fixEmptyAndTrim(workDirPath);
this.failIfWorkDirIsMissing = failIfWorkDirIsMissing;
String internalDirName = Util.fixEmptyAndTrim(internalDir);
this.internalDir = internalDirName != null ? internalDirName : DEFAULT_INTERNAL_DIR;
}
public RemotingWorkDirSettings() {
// Enabled by default
this(false, null, DEFAULT_INTERNAL_DIR, false);
}
/**
* Check if workdir is disabled.
*
* @return {@code true} if the property is disabled.
* In such case Remoting will use the legacy mode.
*/
public boolean isDisabled() {
return disabled;
}
/**
* Indicates that agent root directory should be used as work directory.
*
* @return {@code true} if the agent root should be a work directory.
*/
public boolean isUseAgentRootDir() {
return workDirPath == null;
}
/**
* Check if startup should fail if the workdir is missing.
*
* @return {@code true} if Remoting should fail if the the work directory is missing instead of creating it
*/
public boolean isFailIfWorkDirIsMissing() {
return failIfWorkDirIsMissing;
}
/**
* Gets path to the custom workdir path.
*
* @return Custom workdir path.
* If {@code null}, an agent root directory path should be used instead.
*/
@CheckForNull
public String getWorkDirPath() {
return workDirPath;
}
@Nonnull
public String getInternalDir() {
return internalDir;
}
@Override
public Descriptor<RemotingWorkDirSettings> getDescriptor() {
return Jenkins.getInstance().getDescriptor(RemotingWorkDirSettings.class);
}
/**
* Gets list of command-line arguments for the work directory.
* @param computer Computer, for which the arguments are being created
* @return Non-modifiable list of command-line arguments
*/
public List<String> toCommandLineArgs(@Nonnull SlaveComputer computer) {
if(disabled) {
return Collections.emptyList();
}
ArrayList<String> args = new ArrayList<>();
args.add("-workDir");
if (workDirPath == null) {
Slave node = computer.getNode();
if (node == null) {
// It is not possible to launch this node anyway.
return Collections.emptyList();
}
args.add(node.getRemoteFS());
} else {
args.add(workDirPath);
}
if (!DEFAULT_INTERNAL_DIR.equals(internalDir)) {
args.add("-internalDir");
args.add(internalDir);;
}
if (failIfWorkDirIsMissing) {
args.add(" -failIfWorkDirIsMissing");
}
return Collections.unmodifiableList(args);
}
/**
* Gets a command line string, which can be passed to agent start command.
*
* @param computer Computer, for which the arguments need to be constructed.
* @return Command line arguments.
* It may be empty if the working directory is disabled or
* if the Computer type is not {@link SlaveComputer}.
*/
@Nonnull
@Restricted(NoExternalUse.class)
public String toCommandLineString(@Nonnull SlaveComputer computer) {
if(disabled) {
return "";
}
StringBuilder bldr = new StringBuilder();
bldr.append("-workDir \"");
if (workDirPath == null) {
Slave node = computer.getNode();
if (node == null) {
// It is not possible to launch this node anyway.
return "";
}
bldr.append(node.getRemoteFS());
} else {
bldr.append(workDirPath);
}
bldr.append("\"");
if (!DEFAULT_INTERNAL_DIR.equals(internalDir)) {
bldr.append(" -internalDir \"");
bldr.append(internalDir);
bldr.append("\"");
}
if (failIfWorkDirIsMissing) {
bldr.append(" -failIfWorkDirIsMissing");
}
return bldr.toString();
}
@Extension
public static class DescriptorImpl extends Descriptor<RemotingWorkDirSettings> {
}
/**
* Gets default settings for the disabled work directory.
*
* @return Legacy value: disabled work directory.
*/
@Nonnull
public static RemotingWorkDirSettings getDisabledDefaults() {
return LEGACY_DEFAULT;
}
/**
* Gets default settings of the enabled work directory.
*/
@Nonnull
public static RemotingWorkDirSettings getEnabledDefaults() {
return ENABLED_DEFAULT;
}
}
@@ -170,7 +170,7 @@ public final class ReverseBuildTrigger extends Trigger<Job> implements Dependenc
}
@Override public void buildDependencyGraph(final AbstractProject downstream, DependencyGraph graph) {
for (AbstractProject upstream : Items.fromNameList(downstream.getParent(), upstreamProjects, AbstractProject.class)) {
for (AbstractProject upstream : Items.fromNameList(downstream.getParent(), Util.fixNull(upstreamProjects), AbstractProject.class)) {
graph.addDependency(new DependencyGraph.Dependency(upstream, downstream) {
@Override public boolean shouldTriggerBuild(AbstractBuild upstreamBuild, TaskListener listener, List<Action> actions) {
return shouldTrigger(upstreamBuild, listener);
@@ -253,7 +253,7 @@ public final class ReverseBuildTrigger extends Trigger<Job> implements Dependenc
continue;
}
List<Job> upstreams =
Items.fromNameList(downstream.getParent(), trigger.upstreamProjects, Job.class);
Items.fromNameList(downstream.getParent(), Util.fixNull(trigger.upstreamProjects), Job.class);
LOGGER.log(Level.FINE, "from {0} see upstreams {1}", new Object[]{downstream, upstreams});
for (Job upstream : upstreams) {
if (upstream instanceof AbstractProject && downstream instanceof AbstractProject) {
@@ -310,8 +310,8 @@ public final class ReverseBuildTrigger extends Trigger<Job> implements Dependenc
ReverseBuildTrigger t = ParameterizedJobMixIn.getTrigger(p, ReverseBuildTrigger.class);
if (t != null) {
String revised =
Items.computeRelativeNamesAfterRenaming(oldFullName, newFullName, t.upstreamProjects,
p.getParent());
Items.computeRelativeNamesAfterRenaming(oldFullName, newFullName,
Util.fixNull(t.upstreamProjects), p.getParent());
if (!revised.equals(t.upstreamProjects)) {
t.upstreamProjects = revised;
try {
@@ -0,0 +1,40 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
# About Jenkins {0}
about=\
\u041e\u0442\u043d\u043e\u0441\u043d\u043e Jenkins {0}
# Static resources
static.dependencies=\
\u0421\u0442\u0430\u0442\u0438\u0447\u043d\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0438
# License and dependency information for plugins
plugin.dependencies=\
\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0442\u0435 \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438\u0442\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438\u0442\u0435.
No\ information\ recorded=\
\u041d\u0435 \u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0432\u0430 \u043d\u0438\u043a\u0430\u043a\u0432\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f
# Jenkins depends on the following 3rd party libraries
dependencies=\
Jenkins \u0437\u0430\u0432\u0438\u0441\u0438 \u0438 \u043e\u0442 \u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438 \u043c\u0435\u0441\u0442\u0430
# <a href="https://jenkins.io/">Jenkins</a> is a community-developed open-source automation server.
blurb=\
<a href="https://jenkins.io/">Jenkins</a> \u0435 \u0441\u044a\u0440\u0432\u044a\u0440 \u0437\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u0441\
\u043e\u0442\u0432\u043e\u0440\u0435\u043d \u043a\u043e\u0434, \u043a\u043e\u0439\u0442\u043e \u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0432\u0430 \u043e\u0442 \u0441\u0432\u043e\u044f\u0442\u0430 \u043e\u0431\u0449\u043d\u043e\u0441\u0442 \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438.
@@ -135,3 +135,15 @@ PluginWrapper.obsolete=\
# {0} v{1} failed to load.
PluginWrapper.failed_to_load_plugin=\
\u201e{0}\u201c, \u0432\u0435\u0440\u0441\u0438\u044f {1} \u043d\u0435 \u0441\u0435 \u0437\u0430\u0440\u0435\u0434\u0438.
# Plugins Failed To Load
PluginWrapper.PluginWrapperAdministrativeMonitor.DisplayName=\
\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438\u0442\u0435 \u043d\u0435 \u0441\u0435 \u0437\u0430\u0440\u0435\u0434\u0438\u0445\u0430
# Invalid Plugin Configuration
PluginManager.PluginUpdateMonitor.DisplayName=\
\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430
# Whitespace can no longer be used as the separator. Please Use \u2018,\u2019 as the separator instead.
FilePath.validateAntFileMask.whitespaceSeparator=\
\u0412\u0435\u0447\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0437\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b. \u041f\u043e\u043b\u0437\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043f\u0435\u0442\u0430\u044f: \u201e,\u201c
# Cyclic Dependencies Detector
PluginManager.PluginCycleDependenciesMonitor.DisplayName=\
\u041e\u0442\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0446\u0438\u043a\u043b\u0438\u0447\u043d\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438
@@ -20,7 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
File=\u0424\u0430\u0439\u043b
File=\
\u0424\u0430\u0439\u043b
HTTP\ Proxy\ Configuration=\
\u0421\u044a\u0440\u0432\u044a\u0440-\u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a \u0437\u0430 HTTP
Submit=\
@@ -1,6 +1,6 @@
# The MIT License
#
# Copyright (c) 2004-2016, Sun Microsystems, Damian Szczepanik
# Copyright (c) 2004-2017, Sun Microsystems, Damian Szczepanik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -28,12 +28,14 @@ Restart\ Once\ No\ Jobs\ Are\ Running=Uruchom ponownie gdy \u017Cadne zadania ni
Uncheck\ to\ disable\ the\ plugin=Odznacz aby wy\u0142\u0105czy\u0107 wtyczk\u0119
Uninstall=Odinstaluj
Version=Wersja
downgradeTo=Powr\u00F3\u0107 do starszej wersji {0}
downgradeTo=Powr\u00F3\u0107 do wersji {0}
requires.restart=Wymagane jest ponowne uruchomienie Jenkinsa. Zmiany wtyczek w tym momencie s\u0105 bardzo niewskazane. Uruchom ponownie Jenkinsa, zanim wprowadzisz zmiany.
Uninstallation\ pending=Trwa odinstalowywanie
This\ plugin\ cannot\ be\ disabled=Ta wtyczka nie mo\u017Ce by\u0107 wy\u0142\u0105czona
No\ plugins\ installed.=Brak zainstalowanych wtyczek
This\ plugin\ cannot\ be\ enabled=Ta wtyczka nie mo\u017Ce by\u0107 wy\u0142\u0105czona
This\ plugin\ cannot\ be\ enabled=Ta wtyczka nie mo\u017Ce by\u0107 w\u0142\u0105czona
Update\ Center=Centrum aktualizacji
Filter=Filtruj
No\ description\ available.=Opis nie jest dost\u0119pny
Warning=Ostrze\u017Cenie
New\ plugins\ will\ take\ effect\ once\ you\ restart\ Jenkins=Nowe wtyczki zostan\u0105 w\u0142\u0105czone po ponownym uruchomieniu Jenkinsa.
@@ -1,6 +1,6 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2015, 2016, Alexander Shopov <ash@kambanaria.org>
# Bulgarian translation: Copyright (c) 2015, 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -61,3 +61,8 @@ depCompatWarning=\
\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u0442\u0430\u0437\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u0438\u0437\u0438\u0441\u043a\u0432\u0430 \u043e\u0431\u043d\u043e\u0432\u044f\u0432\u0430\u043d\u0435 \u043d\u0430 \u0437\u0430\u0432\u0438\u0441\u0435\u0449\u0438\u0442\u0435 \u043e\u0442 \u043d\u0435\u044f\
\u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438. \u0427\u0430\u0441\u0442 \u043e\u0442 \u0442\u044f\u0445 \u043d\u0435 \u0441\u0430 \u0441\u044a\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0438 \u0441 \u0442\u0435\u043a\u0443\u0449\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Jenkins. \u0429\u0435\
\u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u0437\u0430\u0434\u0430\u0447\u0438\u0442\u0435, \u043a\u043e\u0438\u0442\u043e \u0433\u0438 \u043f\u043e\u043b\u0437\u0432\u0430\u0442.
# \
# Warning: This plugin version may not be safe to use. Please review the following security notices:
securityWarning=\
\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u0442\u0430\u0437\u0438 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0438\u043c\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u044a\u0441\
\u0441\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442\u0442\u0430. \u041f\u0440\u0435\u0433\u043b\u0435\u0434\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f\u0442\u0430.
@@ -0,0 +1,27 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
Correct=\
\u041e\u0442\u0433\u043e\u0432\u0430\u0440\u044f
# There are dependency errors loading some plugins
Dependency\ errors=\
\u0418\u043c\u0430 \u0433\u0440\u0435\u0448\u043a\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438\u0442\u0435 \u043d\u0430 \u043d\u044f\u043a\u043e\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438
@@ -1,6 +1,6 @@
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
# Copyright (c) 2004-2017, Sun Microsystems, Inc, Damian Szczepanik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -23,4 +23,6 @@
Password=Has\u0142o
Port=Port
Server=Serwer
User\ name=Nazwa u\u017cytkownika
User\ name=Nazwa u\u017Cytkownika
No\ Proxy\ Host=Brak hosta proxy
Validate\ Proxy=Sprawd\u017A proxy
@@ -0,0 +1,13 @@
<div>
Ако вашият Jenkins е зад защитна стена и няма пряка връзка към Интернет, а JVM на сървъра не е
настроена правилно, за да се позволи връзка с Интернет, може да укажете име на сървър-посредник
за HTTP, за да позволите на Jenkins самостоятелно да инсталира приставки. (за повече детайли:
<a href="http://download.oracle.com/javase/6/docs/technotes/guides/net/properties.html">Networking Properties</a>)
Jenkins използва HTTPS, за да се свърже със сървъра за обновяване и изтегли приставките.
<p>
Ако полето е празно, Jenkins ще се свързва директно с Интернет.
<p>
Ако не сте сигурни, вижте какви са настройките на браузъра ви.
</div>
@@ -0,0 +1,4 @@
<div>
Шаблони за имената на сървърите, към които да се свързва директно, а не през сървъра-посредник.
По един шаблон на ред. „*“ напасва всички имена (напр. „*.cloudbees.com“ или „w*.jenkins.io“)
</div>
@@ -0,0 +1,3 @@
<div>
Това поле определя порта за сървъра-посредник по HTTP.
</div>
@@ -0,0 +1,9 @@
<div>
Това поле определя името за идентификация пред сървъра-посредник .
<p>
Ако този сървър-посредник ползва схемата да идентификация на
Microsoft: <a href="http://en.wikipedia.org/wiki/NTLM">NTLM</a>,
то името за домейна се добавя пред потребителското име с
разделител „\“. Например: „ACME\John Doo“".
</div>
@@ -0,0 +1,36 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, 2017 Alexander Shopov <ash@kambanaria.org>
#
# 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.
Available\ Commands=\
\u041d\u0430\u043b\u0438\u0447\u043d\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0438
# You can access various features in Jenkins through a command-line tool. See \
# <a href="https://jenkins.io/redirect/cli">the Wiki</a> for more details of this feature.\
# To get started, download <a href="{0}/jnlpJars/jenkins-cli.jar">jenkins-cli.jar</a>, and run it as follows:
blurb=\
\u0418\u043c\u0430\u0442\u0435 \u0434\u043e\u0441\u0442\u044a\u043f \u0434\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043d\u043e\u0441\u0442\u0442\u0430 \u043d\u0430 Jenkins \u0447\u0440\u0435\u0437 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u0437\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0438\u044f \u0440\u0435\u0434.\
\u0417\u0430 \u043f\u043e\u0432\u0435\u0447\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0433\u043b\u0435\u0434\u0430\u0439\u0442\u0435\
<a href="https://jenkins.io/redirect/cli">\u0443\u0438\u043a\u0438\u0442\u043e</a>.\
\u0421\u0432\u0430\u043b\u0435\u0442\u0435 \u0444\u0430\u0439\u043b\u0430 <a href="{0}/jnlpJars/jenkins-cli.jar">jenkins-cli.jar</a> \u0438 \u0433\u043e\
\u0438\u0437\u043f\u044a\u043b\u043d\u0435\u0442\u0435 \u043f\u043e \u0441\u043b\u0435\u0434\u043d\u0438\u044f \u043d\u0430\u0447\u0438\u043d:
# Jenkins CLI
Jenkins\ CLI=\
Jenkins \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0438\u044f \u0440\u0435\u0434
@@ -0,0 +1,4 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core">
${%message}
</j:jelly>
@@ -0,0 +1,2 @@
message=This protocol is an obsolete protocol, which has been replaced by CLI2-connect. \
It is also not encrypted.
@@ -0,0 +1,26 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
# This protocol is an obsolete protocol, which has been replaced by CLI2-connect. \
# It is also not encrypted.
message=\
\u0422\u043e\u0437\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0435 \u043e\u0441\u0442\u0430\u0440\u044f\u043b \u0438 \u0435 \u0431\u0435\u0437 \u0448\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0435. \u0417\u0430\u043c\u0435\u043d\u0435\u043d \u0435 \u043e\u0442 CLI2-connect.
@@ -0,0 +1,28 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
Accepts\ connections\ from\ CLI\ clients=\
\u041f\u0440\u0438\u0435\u043c\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0438\u0442\u0435 \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0438\u044f \u0440\u0435\u0434.
# Accepts connections from CLI clients. This protocol is unencrypted.
summary=\
\u041f\u0440\u0438\u0435\u043c\u0430\u043d\u0435 \u043d\u0430 \u0432\u0440\u044a\u0437\u043a\u0438 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0438\u0442\u0435 \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0438\u044f \u0440\u0435\u0434. \u0422\u043e\u0437\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043d\u0435 \u0435 \u0437\u0430\u0449\u0438\u0442\u0435\u043d\
\u0441 \u0448\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0435.
@@ -0,0 +1,4 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core">
${%message}
</j:jelly>
@@ -0,0 +1,3 @@
message=Remoting-based CLI is deprecated and not recommended due to the security reasons. \
It is recommended to disable this protocol on the instance. \
if you need Remoting CLI on your instance, this protocol has to be enabled.
@@ -0,0 +1,29 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
# Remoting-based CLI is deprecated and not recommended due to the security reasons. \
# It is recommended to disable this protocol on the instance. \
# if you need Remoting CLI on your instance, this protocol has to be enabled.
message=\
\u041e\u0442\u0434\u0430\u043b\u0435\u0447\u0435\u043d\u0438\u0442\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0438 \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0435\u043d \u0440\u0435\u0434 \u0441\u0430 \u043e\u0441\u0442\u0430\u0440\u0435\u043b\u0438 \u0438 \u043d\u0435 \u0441\u0435 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430\u0442 \u0437\u0430\u0440\u0430\u0434\u0438\
\u043d\u0438\u0441\u043a\u0430\u0442\u0430 \u0438\u043c \u0441\u0438\u0433\u0443\u0440\u043d\u043e\u0441\u0442. \u041e\u0441\u0432\u0435\u043d \u0430\u043a\u043e \u043d\u0430\u0438\u0441\u0442\u0438\u043d\u0430 \u0441\u0435 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0435 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0442\u043e\u0437\u0438\
\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0432\u0438 \u043f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0432\u0430\u043c\u0435 \u0434\u0430 \u0433\u043e \u0438\u0437\u043a\u043b\u044e\u0447\u0438\u0442\u0435.
@@ -0,0 +1,27 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
Extends\ the\ version\ 1\ protocol\ by\ adding\ transport\ encryption=\
\u0420\u0430\u0437\u0448\u0438\u0440\u044f\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f 1 \u043d\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043a\u0430\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u044f \u0448\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0435
# Extends the version 1 protocol by adding transport encryption.
summary=\
\u0420\u0430\u0437\u0448\u0438\u0440\u044f\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f 1 \u043d\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043a\u0430\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u044f \u0448\u0438\u0444\u0440\u0438\u0440\u0430\u043d\u0435
@@ -1,6 +1,6 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2015, 2016, Alexander Shopov <ash@kambanaria.org>
# Bulgarian translation: Copyright (c) 2015, 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -159,3 +159,29 @@ CliProtocol2.displayName=\
# Jenkins CLI Protocol/1
CliProtocol.displayName=\
\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043d\u0430 Jenkins \u0437\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0435\u043d \u0440\u0435\u0434, \u0432\u0435\u0440\u0441\u0438\u044f 1
# \
# Depending on the security realm, you will need to pass something like:\n\
# --username USER [ --password PASS | --password-file FILE ]\n\
# May not be supported in some security realms, such as single-sign-on.\n\
# Pair with the logout command.\n\
# The same options can be used on any other command, but unlike other generic CLI options,\n\
# these come *after* the command name.\n\
# Whether stored or not, this authentication mode will not let you refer to (e.g.) jobs as arguments\n\
# if Jenkins denies anonymous users Overall/Read and (e.g.) Job/Read.\n\
# *Deprecated* in favor of -auth.
LoginCommand.FullDescription=\
\u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442 \u043e\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u0449\u0435 \u0441\u0435 \u043d\u0430\u043b\u043e\u0436\u0438 \u0434\u0430 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442\u0435 \u043d\u0435\u0449\u043e \u043a\u0430\u0442\u043e:\n\
--username \u041f\u041e\u0422\u0420\u0415\u0411\u0418\u0422\u0415\u041b [ --password \u041f\u0410\u0420\u041e\u041b\u0410 | --password-file \u0424\u0410\u0419\u041b ]\n\
\u0412\u044a\u0437\u043c\u043e\u0436\u043d\u043e \u0435 \u0434\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0438 \u0432\u044a\u0432 \u0432\u0441\u0438\u0447\u043a\u0438 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043d\u0430\u043f\u0440. \u043f\u0440\u0438 \u0435\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u0432\u043f\u0438\u0441\u0432\u0430\u043d\u0435.\n\
\u041a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0430\u0439\u0442\u0435 \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0442\u0430 \u0437\u0430 \u0438\u0437\u0445\u043e\u0434.\n\
\u0422\u0435\u0437\u0438 \u043e\u043f\u0446\u0438\u0438 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0442 \u0441 \u0432\u0441\u044f\u043a\u0430 \u0434\u0440\u0443\u0433\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u043d\u043e \u0437\u0430 \u0440\u0430\u0437\u043b\u0438\u043a\u0430 \u043e\u0442\
\u043e\u0442 \u043e\u0441\u0442\u0430\u043d\u0430\u043b\u0438\u0442\u0435 \u043e\u0431\u0449\u0438 \u043e\u043f\u0446\u0438\u0438 \u0437\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0435\u043d \u0440\u0435\u0434, \u0442\u0435 \u0441\u0435 \u043f\u043e\u0434\u0430\u0432\u0430\u0442 \u0421\u041b\u0415\u0414 \u0438\u043c\u0435\u0442\u043e \u043d\u0430\
\u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0442\u0430. \u0422\u043e\u0437\u0438 \u0440\u0435\u0436\u0438\u043c \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0432\u0430 \u0434\u0430 \u0443\u043a\u0430\u0437\u0432\u0430\u0442\u0435 \u0438\u0437\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0438\u044f\u0442\u0430 \u043a\u0430\u0442\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0438,\
\u0430\u043a\u043e Jenkins \u043d\u0435 \u0434\u0430\u0432\u0430 \u043d\u0430 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u0438\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043e\u0431\u0449\u043e \u043f\u0440\u0430\u0432\u043e \u0437\u0430 \u0447\u0435\u0442\u0435\u043d\u0435.\
\u041e\u0421\u0422\u0410\u0420\u042f\u041b\u041e, \u0434\u0430 \u043d\u0435 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430! \u041f\u0440\u043e\u0431\u0432\u0430\u0439\u0442\u0435 \u0441 \u201e-auth\u201c \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0432\u0430.
# Installing a plugin from standard input
InstallPluginCommand.InstallingPluginFromStdin=\
\u0418\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430 \u043e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u044f \u0432\u0445\u043e\u0434.
# *Deprecated* in favor of -auth.
LogoutCommand.FullDescription=\
\u041e\u0421\u0422\u0410\u0420\u042f\u041b\u041e, \u0434\u0430 \u043d\u0435 \u0441\u0435 \u043f\u043e\u043b\u0437\u0432\u0430! \u041f\u0440\u043e\u0431\u0432\u0430\u0439\u0442\u0435 \u0441 \u201e-auth\u201c \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0432\u0430.
@@ -0,0 +1,48 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, 2017, Alexander Shopov <ash@kambanaria.org>
#
# 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.
# Clean up some files from this partition to make more room.
solution.1=\
\u0418\u0437\u0442\u0440\u0438\u0439\u0442\u0435 \u0447\u0430\u0441\u0442 \u043e\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0435\u0442\u0435 \u043e\u0442 \u0442\u043e\u0437\u0438 \u0434\u044f\u043b, \u0437\u0430 \u0434\u0430 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u0435 \u043f\u043e\u0432\u0435\u0447\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e.
# \
# Move <tt>JENKINS_HOME</tt> to a bigger partition. \
# See <a href="https://jenkins.io/redirect/migrate-jenkins-home">our Wiki</a> for how to do this.
solution.2=\
\u041f\u0440\u0435\u043c\u0435\u0441\u0442\u0435\u0442\u0435 <tt>JENKINS_HOME</tt> \u043d\u0430 \u043f\u043e-\u0433\u043e\u043b\u044f\u043c \u0434\u044f\u043b.\
\u0412\u0438\u0436\u0442\u0435: <a href="https://jenkins.io/redirect/migrate-jenkins-home">\
\u0443\u0438\u043a\u0438\u0442\u043e</a> \u0437\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0442\u043e\u0432\u0430.
# <tt>JENKINS_HOME</tt> is almost full
blurb=\
\u0424\u0430\u0439\u043b\u043e\u0432\u0430\u0442\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u043d\u0430 \u043a\u043e\u044f\u0442\u043e \u0435 <tt>JENKINS_HOME</tt>, \u0435 \u043f\u043e\u0447\u0442\u0438 \u043f\u044a\u043b\u043d\u0430
JENKINS_HOME\ is\ almost\ full=\
\u0424\u0430\u0439\u043b\u043e\u0432\u0430\u0442\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u043d\u0430 \u043a\u043e\u044f\u0442\u043e \u0435 JENKINS_HOME, \u0435 \u043f\u043e\u0447\u0442\u0438 \u043f\u044a\u043b\u043d\u0430
# \
# Your <tt>JENKINS_HOME</tt> ({0}) is almost full. \
# When this directory completely fills up, it\'ll wreak havoc because Jenkins can\'t store any more data.
description.1=\
\
\u0424\u0430\u0439\u043b\u043e\u0432\u0430\u0442\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 {0}, \u043d\u0430 \u043a\u043e\u044f\u0442\u043e \u0435 <tt>JENKINS_HOME</tt> ({0}) \u0435 \u043f\u043e\u0447\u0442\u0438 \u043f\u044a\u043b\u043d\u0430.\
\u041a\u043e\u0433\u0430\u0442\u043e \u0434\u0438\u0441\u043a\u043e\u0432\u043e\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0441\u0432\u044a\u0440\u0448\u0438, Jenkinns \u043d\u044f\u043c\u0430 \u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e, \u0437\u0430\u0449\u043e\u0442\u043e\
\u043d\u044f\u043c\u0430 \u043a\u044a\u0434\u0435 \u0434\u0430 \u0441\u044a\u0445\u0440\u0430\u043d\u044f\u0432\u0430 \u043d\u043e\u0432\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u0438.
# To prevent that problem, you should act now.
description.2=\
\u0422\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0440\u0435\u0430\u0433\u0438\u0440\u0430\u0442\u0435 \u043d\u0435\u0437\u0430\u0431\u0430\u0432\u043d\u043e, \u0437\u0430 \u0434\u0430 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u0435 \u0442\u043e\u0437\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.
Loaded 100 of 503 files, more files were not shown because too many files have changed in this diff. Show more