forked from I2P_Developers/i2p.i2p
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user