Skip to content

Commit

Permalink
fix crumb issue with Jenkins 2.176.2+/2.186+
Browse files Browse the repository at this point in the history
Always pass the JSESSIONID in addition to the crumb
See https://jenkins.io/security/advisory/2019-07-17/#SECURITY-626

Closes cdancy#67
  • Loading branch information
tbouffard committed Oct 10, 2019
1 parent 602d32b commit 6dc4120
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 9 deletions.
26 changes: 21 additions & 5 deletions src/main/java/com/cdancy/jenkins/rest/domain/crumb/Crumb.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,34 @@

import com.cdancy.jenkins.rest.domain.common.Error;
import com.cdancy.jenkins.rest.domain.common.ErrorsHolder;
import com.cdancy.jenkins.rest.domain.common.Value;
import com.cdancy.jenkins.rest.JenkinsUtils;
import com.google.auto.value.AutoValue;

@AutoValue
public abstract class Crumb implements Value<String>, ErrorsHolder {
public abstract class Crumb implements ErrorsHolder {

@Nullable
public abstract String value();

@Nullable
public abstract String sessionIdCookie();

@SerializedNames({ "value", "errors" })
public static Crumb create(@Nullable final String value,
public static Crumb create(final String value,
final List<Error> errors) {

return create(value, null, errors);
}

@SerializedNames({ "value", "sessionIdCookie" })
public static Crumb create(final String value, final String sessionIdCookie) {
return create(value, sessionIdCookie, null);
}

private static Crumb create(final String value, final String sessionIdCookie,
final List<Error> errors) {

return new AutoValue_Crumb(value,
JenkinsUtils.nullToEmpty(errors));
return new AutoValue_Crumb(JenkinsUtils.nullToEmpty(errors), value,
sessionIdCookie);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class JenkinsAuthenticationFilter implements HttpRequestFilter {
private final JenkinsApi jenkinsApi;

// key = Crumb, value = true if exception is ResourceNotFoundException false otherwise
private static volatile Pair<Crumb, Boolean> crumbPair = null;
private static volatile Pair<Crumb, Boolean> crumbPair = null;
private static final String CRUMB_HEADER = "Jenkins-Crumb";

@Inject
Expand All @@ -61,6 +61,7 @@ public HttpRequest filter(final HttpRequest request) throws HttpException {
final Pair<Crumb, Boolean> localCrumb = getCrumb();
if (localCrumb.getKey().value() != null) {
builder.addHeader(CRUMB_HEADER, localCrumb.getKey().value());
builder.addHeader(HttpHeaders.COOKIE, localCrumb.getKey().sessionIdCookie());
} else {
if (localCrumb.getValue() == false) {
throw new RuntimeException("Unexpected exception being thrown: error=" + localCrumb.getKey().errors().get(0));
Expand All @@ -87,7 +88,7 @@ private Pair<Crumb, Boolean> getCrumb() {
}
return crumbValueInit;
}

// simple impl/copy of javafx.util.Pair
private class Pair<A, B> {
private final A a;
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/com/cdancy/jenkins/rest/parsers/CrumbParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.io.IOException;

import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;

import org.jclouds.http.HttpResponse;
import org.jclouds.util.Strings2;
Expand All @@ -38,13 +39,24 @@ public Crumb apply(final HttpResponse input) {
final int statusCode = input.getStatusCode();
if (statusCode >= 200 && statusCode < 400) {
try {
final String response = Strings2.toStringAndClose(input.getPayload().openStream());
return Crumb.create(response.split(":")[1], null);
return Crumb.create(crumbValue(input), sessionIdCookie(input));
} catch (final IOException e) {
throw new RuntimeException(input.getStatusLine(), e);
}
} else {
throw new RuntimeException(input.getStatusLine());
}
}

private static String crumbValue(HttpResponse input) throws IOException {
return Strings2.toStringAndClose(input.getPayload().openStream())
.split(":")[1];
}

private static String sessionIdCookie(HttpResponse input) {
return input.getHeaders().get(HttpHeaders.SET_COOKIE).stream()
.filter(c -> c.startsWith("JSESSIONID"))
.findFirst()
.orElse(null);
}
}

0 comments on commit 6dc4120

Please sign in to comment.