Skip to content

Commit

Permalink
Added support for ipv4/ipv6 CIDR notation to WhitelistVerifer; includ…
Browse files Browse the repository at this point in the history
…es methods for form field validation.
  • Loading branch information
TheTekton committed Nov 10, 2019
1 parent e6daab9 commit db13a2b
Showing 1 changed file with 151 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@

import static org.jenkinsci.plugins.gwt.whitelist.HMACVerifier.hmacVerify;

import com.github.jgonian.ipmath.Ipv4;
import com.github.jgonian.ipmath.Ipv4Range;
import com.github.jgonian.ipmath.Ipv6;
import com.github.jgonian.ipmath.Ipv6Range;
import com.google.common.base.Optional;
import com.google.common.net.InetAddresses;
import hudson.util.FormValidation;
import java.util.List;
import java.util.Map;
import org.jenkinsci.plugins.gwt.global.CredentialsHelper;
import org.jenkinsci.plugins.gwt.global.Whitelist;
import org.jenkinsci.plugins.gwt.global.WhitelistItem;
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
import org.kohsuke.stapler.QueryParameter;

public class WhitelistVerifier {

Expand Down Expand Up @@ -43,13 +50,104 @@ static void doVerifyWhitelist(
throw new WhitelistException("Did not find a matching whitelisted host:\n" + messagesString);
}

/** Returns true if whitelistHost CIDR block contains remoteHost; supports ipv4/ipv6. */
static boolean verifyCIDR(
final String remoteHost, final String whitelistHostCIDR, final String whitelistHostIP)
throws WhitelistException {

int whitelistHostLength = InetAddresses.forString(whitelistHostIP).getAddress().length;
int remoteHostLength = InetAddresses.forString(remoteHost).getAddress().length;
if (whitelistHostLength == 4) {
if (remoteHostLength == 4) {
Ipv4Range whitelistHostRange = Ipv4Range.parse(whitelistHostCIDR);
return whitelistHostRange.overlaps(Ipv4Range.parse(remoteHost + "/32"));
}
} else if (whitelistHostLength == 16) {
if (remoteHostLength == 16) {
Ipv6Range whitelistHostRange = Ipv6Range.parse(whitelistHostCIDR);
return whitelistHostRange.overlaps(Ipv6Range.parse(remoteHost + "/128"));
}
}

return false;
}

static boolean verifyIpv4(final String remoteHost, final String whitelistHost)
throws WhitelistException {
Ipv4 whitelistIP = Ipv4.parse(whitelistHost);
return whitelistIP.equals(Ipv4.parse(remoteHost));
}

static boolean verifyIpv6(final String remoteHost, final String whitelistHost)
throws WhitelistException {
Ipv6 whitelistIP = Ipv6.parse(whitelistHost);
return whitelistIP.equals(Ipv6.parse(remoteHost));
}

/** Returns true if whitelistHost is equal to remoteHost; supports ipv4/ipv6. */
static boolean verifyIP(final String remoteHost, final String whitelistHost)
throws WhitelistException {

int whitelistHostLength = InetAddresses.forString(whitelistHost).getAddress().length;
int remoteHostLength = InetAddresses.forString(remoteHost).getAddress().length;
if (whitelistHostLength == 4) {
if (remoteHostLength == 4) {
return verifyIpv4(whitelistHost, remoteHost);
}
} else if (whitelistHostLength == 16) {
if (remoteHostLength == 16) {
return verifyIpv6(whitelistHost, remoteHost);
}
}

return false;
}

/** Returns true if whitelistHost contains remoteHost; supports ip/cidr. */
static Boolean whitelistContains(final String remoteHost, final String whitelistHost)
throws WhitelistException {
Boolean isMatched = false;

if (whitelistHost.equalsIgnoreCase(remoteHost)) {
isMatched = true;
}

Boolean isCIDR = false;
Boolean isRange = false;

String[] hostParts = whitelistHost.split("/");

String whitelistHostIP;
if (hostParts.length == 2) {
whitelistHostIP = hostParts[0];
isCIDR = true;
} else {
hostParts = whitelistHost.split("-");
if (hostParts.length == 2) {
isRange = true;
}
}

if (isCIDR || isRange) {
whitelistHostIP = hostParts[0];
isMatched = verifyCIDR(remoteHost, whitelistHost, whitelistHostIP);
} else {
isMatched = verifyIP(remoteHost, whitelistHost);
}

return isMatched;
}

static void whitelistVerify(
final String remoteHost,
final WhitelistItem whitelistItem,
final Map<String, List<String>> headers,
final String postContent)
throws WhitelistException {
if (whitelistItem.getHost().equalsIgnoreCase(remoteHost)) {

String whitelistHost = whitelistItem.getHost();

if (whitelistContains(remoteHost, whitelistHost)) {
if (whitelistItem.isHmacEnabled()) {
final Optional<StringCredentials> hmacKeyOpt =
CredentialsHelper.findCredentials(whitelistItem.getHmacCredentialId());
Expand All @@ -68,4 +166,56 @@ static void whitelistVerify(
throw new WhitelistException(
"Sending host \"" + remoteHost + "\" was not matched by whitelist.");
}

private Boolean validateIpValue(String ipValue) {
Boolean isValid = false;

Boolean isCIDR = false;
Boolean isRange = false;

String[] hostParts = ipValue.split("/");

if (hostParts.length == 2) {
isCIDR = true;
} else {
hostParts = ipValue.split("-");
if (hostParts.length == 2) {
isRange = true;
}
}

if (isCIDR || isRange) {
int leftValueLength = InetAddresses.forString(hostParts[0]).getAddress().length;
if (leftValueLength == 4) {
if (Ipv4Range.parse(ipValue) != null) {
isValid = true;
}
} else if (leftValueLength == 16) {
if (Ipv6Range.parse(ipValue) != null) {
isValid = true;
}
}
} else {
int ipValueLength = InetAddresses.forString(hostParts[0]).getAddress().length;
if (ipValueLength == 4) {
if (Ipv4.parse(ipValue) != null) {
isValid = true;
}
} else if (ipValueLength == 16) {
if (Ipv6.parse(ipValue) != null) {
isValid = true;
}
}
}

return isValid;
}

public FormValidation checkIP(@QueryParameter String value) {
if (validateIpValue(value)) {
return FormValidation.ok();
} else {
return FormValidation.error("IP Address must be in IPV4 or IPV6 CIDR or IP range notation.");
}
}
}

0 comments on commit db13a2b

Please sign in to comment.