i2ptunnel, eepget: Add support for SHA-256 digest proxy auth (RFC 7616)

Requires re-saving user/pw on proxy side
This commit is contained in:
zzz
2022-09-20 08:26:05 -04:00
parent ab49a149ba
commit c1b241ab8f
6 changed files with 148 additions and 34 deletions

View File

@@ -1785,20 +1785,38 @@ public class EepGet {
// use standard alphabet
authMode = AUTH_MODE.BASIC;
authChallenge = auth.substring(6);
args = parseAuthArgs(authChallenge);
}
} else if (authLC.startsWith("digest ")) {
// better than anything
authMode = AUTH_MODE.DIGEST;
authChallenge = auth.substring(7);
// RFC 7616 take the first one that we support
if (authMode != AUTH_MODE.DIGEST) {
String ac = auth.substring(7);
Map<String, String> aargs = parseAuthArgs(ac);
String algo = aargs.get("algorithm");
if (algo != null) {
algo = algo.toLowerCase(Locale.US);
if (!algo.equals("sha-256") && !algo.equals("md5")) {
if (_log.shouldWarn())
_log.warn("Unsupported auth algorithm " + algo);
return;
}
}
authMode = AUTH_MODE.DIGEST;
authChallenge = ac;
args = aargs;
} else {
if (_log.shouldDebug())
_log.debug("Ignoring auth algorithm " + auth);
}
} else {
// better than NONE only
if (authMode == AUTH_MODE.NONE) {
authMode = AUTH_MODE.UNKNOWN;
authChallenge = null;
args = null;
}
}
nonceCount = 0;
args = null;
}
public String getAuthHeader(String method, String uri) throws IOException {
@@ -1812,8 +1830,6 @@ public class EepGet {
case DIGEST:
if (authChallenge == null)
throw new IOException("Bad proxy auth response");
if (args == null)
args = parseAuthArgs(authChallenge);
Map<String, String> outArgs = generateAuthArgs(method, uri);
if (outArgs == null)
throw new IOException("Bad proxy auth response");
@@ -1842,7 +1858,14 @@ public class EepGet {
String nonce = args.get("nonce");
String qop = args.get("qop");
String opaque = args.get("opaque");
//String algorithm = args.get("algorithm");
// RFC 7616
String algorithm = args.get("algorithm");
boolean isSHA256 = false;
if (algorithm == null)
algorithm = "MD5";
else
isSHA256 = algorithm.toLowerCase(Locale.US).equals("sha-256");
rv.put("algorithm", algorithm);
//String stale = args.get("stale");
if (realm == null || nonce == null) {
if (_log.shouldLog(Log.INFO))
@@ -1872,13 +1895,14 @@ public class EepGet {
}
// get H(A1)
String ha1 = PasswordManager.md5Hex(username + ':' + realm + ':' + password);
String a1 = username + ':' + realm + ':' + password;
String ha1 = isSHA256 ? PasswordManager.sha256Hex(a1) : PasswordManager.md5Hex(a1);
// get H(A2)
String a2 = method + ':' + uri;
String ha2 = PasswordManager.md5Hex(a2);
String ha2 = isSHA256 ? PasswordManager.sha256Hex(a2) : PasswordManager.md5Hex(a2);
// response
String kd = ha1 + ':' + nonce + kdMiddle + ':' + ha2;
rv.put("response", '"' + PasswordManager.md5Hex(kd) + '"');
rv.put("response", '"' + (isSHA256 ? PasswordManager.sha256Hex(kd) : PasswordManager.md5Hex(kd)) + '"');
return rv;
}

View File

@@ -5,6 +5,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import net.i2p.I2PAppContext;
import net.i2p.crypto.SHA256Generator;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.SessionKey;
@@ -232,6 +233,38 @@ public class PasswordManager {
return null;
}
/**
* Straight SHA256, no salt
* Will return the SHA256 sum of "user:subrealm:pw", compatible with RFC 7616.
* NOT currently supported by Jetty.
*
* @param subrealm to be used in creating the checksum
* @param user non-null, non-empty, already trimmed
* @param pw non-null, plain text, already trimmed
* @return lower-case hex with leading zeros, 32 chars, or null on error
* @since 0.9.56
*/
public static String sha256Hex(String subrealm, String user, String pw) {
String fullpw = user + ':' + subrealm + ':' + pw;
return sha256Hex(fullpw);
}
/**
* Return the SHA256 sum of the data, compatible with RFC 7616.
* NOT currently supported by Jetty.
*
* @param fullpw non-null, plain text, already trimmed
* @return lower-case hex with leading zeros, 64 chars, or null on error
* @since 0.9.56
*/
public static String sha256Hex(String fullpw) {
byte[] data = DataHelper.getUTF8(fullpw);
byte[] sum = new byte[32];
SHA256Generator.getInstance().calculateHash(data, 0, data.length, sum, 0);
// adds leading zeros if necessary
return DataHelper.toString(sum);
}
/**
* speed/comparison test before removing BC version;
* JVM was slightly faster