public HTTPProxy(Uri address, Credentials credentials, bool isTransparent, bool sendWholeUri, bool nonTransparentForHTTPS) { this.Address = address; this.Credentials = credentials; this.IsTransparent = isTransparent; this.SendWholeUri = sendWholeUri; this.NonTransparentForHTTPS = nonTransparentForHTTPS; }
public HTTPProxy(Uri address, Credentials credentials, bool isTransparent, bool sendWholeUri) : this(address, credentials, isTransparent, true, true) { }
public HTTPProxy(Uri address, Credentials credentials) :this(address, credentials, false) {}
/// <summary> /// Generates a string that can be set to an Authorization header. /// </summary> public string GenerateResponseHeader(HTTPRequest request, Credentials credentials) { try { switch (Type) { case AuthenticationTypes.Basic: return string.Concat("Basic ", Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", credentials.UserName, credentials.Password)))); case AuthenticationTypes.Digest: { NonceCount++; string HA1 = string.Empty; // The cnonce-value is an opaque quoted string value provided by the client and used by both client and server to avoid chosen plaintext attacks, to provide mutual // authentication, and to provide some message integrity protection. string cnonce = new System.Random(request.GetHashCode()).Next(int.MinValue, int.MaxValue).ToString("X8"); string ncvalue = NonceCount.ToString("X8"); switch (Algorithm.TrimAndLower()) { case "md5": HA1 = string.Format("{0}:{1}:{2}", credentials.UserName, Realm, credentials.Password).CalculateMD5Hash(); break; case "md5-sess": if (string.IsNullOrEmpty(this.HA1Sess)) this.HA1Sess = string.Format("{0}:{1}:{2}:{3}:{4}", credentials.UserName, Realm, credentials.Password, Nonce, ncvalue).CalculateMD5Hash(); HA1 = this.HA1Sess; break; default: //throw new NotSupportedException("Not supported hash algorithm found in Web Authentication: " + Algorithm); return string.Empty; } // A string of 32 hex digits, which proves that the user knows a password. Set according to the qop value. string response = string.Empty; // The server sent QoP-value can be a list of supported methodes(if sent at all - in this case it's null). // The rfc is not specify that this is a space or comma separeted list. So it can be "auth, auth-int" or "auth auth-int". // We will first check the longer value("auth-int") then the short one ("auth"). If one matches we will reset the qop to the exact value. string qop = this.QualityOfProtections != null ? this.QualityOfProtections.TrimAndLower() : null; if (qop == null) { string HA2 = string.Concat(request.MethodType.ToString().ToUpper(), ":", request.CurrentUri.PathAndQuery).CalculateMD5Hash(); response = string.Format("{0}:{1}:{2}", HA1, Nonce, HA2).CalculateMD5Hash(); } else if (qop.Contains("auth-int")) { qop = "auth-int"; byte[] entityBody = request.GetEntityBody(); if (entityBody == null) entityBody = string.Empty.GetASCIIBytes(); string HA2 = string.Format("{0}:{1}:{2}", request.MethodType.ToString().ToUpper(), request.CurrentUri.PathAndQuery, entityBody.CalculateMD5Hash()).CalculateMD5Hash(); response = string.Format("{0}:{1}:{2}:{3}:{4}:{5}", HA1, Nonce, ncvalue, cnonce, qop, HA2).CalculateMD5Hash(); } else if (qop.Contains("auth")) { qop = "auth"; string HA2 = string.Concat(request.MethodType.ToString().ToUpper(), ":", request.CurrentUri.PathAndQuery).CalculateMD5Hash(); response = string.Format("{0}:{1}:{2}:{3}:{4}:{5}", HA1, Nonce, ncvalue, cnonce, qop, HA2).CalculateMD5Hash(); } else //throw new NotSupportedException("Unrecognized Quality of Protection value found: " + this.QualityOfProtections); return string.Empty; string result = string.Format("Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", cnonce=\"{4}\", response=\"{5}\"", credentials.UserName, Realm, Nonce, request.Uri.PathAndQuery, cnonce, response); if (qop != null) result += String.Concat(", qop=\"", qop, "\", nc=", ncvalue); if (!string.IsNullOrEmpty(Opaque)) result = String.Concat(result, ", opaque=\"", Opaque, "\""); return result; }// end of case "digest": default: break; } } catch { } return string.Empty; }
public HTTPProxy(Uri address, Credentials credentials, bool isTransparent) { this.Address = address; this.Credentials = credentials; this.IsTransparent = isTransparent; }
/// <summary> /// Generates a string that can be set to an Authorization header. /// </summary> public string GenerateResponseHeader(HTTPRequest request, Credentials credentials, bool isProxy = false) { try { switch (Type) { case AuthenticationTypes.Basic: return(string.Concat("Basic ", Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", credentials.UserName, credentials.Password))))); case AuthenticationTypes.Digest: { NonceCount++; string HA1 = string.Empty; // The cnonce-value is an opaque quoted string value provided by the client and used by both client and server to avoid chosen plaintext attacks, to provide mutual // authentication, and to provide some message integrity protection. string cnonce = new System.Random(request.GetHashCode()).Next(int.MinValue, int.MaxValue).ToString("X8"); string ncvalue = NonceCount.ToString("X8"); switch (Algorithm.TrimAndLower()) { case "md5": HA1 = string.Format("{0}:{1}:{2}", credentials.UserName, Realm, credentials.Password).CalculateMD5Hash(); break; case "md5-sess": if (string.IsNullOrEmpty(this.HA1Sess)) { this.HA1Sess = string.Format("{0}:{1}:{2}:{3}:{4}", credentials.UserName, Realm, credentials.Password, Nonce, ncvalue).CalculateMD5Hash(); } HA1 = this.HA1Sess; break; default: //throw new NotSupportedException("Not supported hash algorithm found in Web Authentication: " + Algorithm); return(string.Empty); } // A string of 32 hex digits, which proves that the user knows a password. Set according to the qop value. string response = string.Empty; // The server sent QoP-value can be a list of supported methodes(if sent at all - in this case it's null). // The rfc is not specify that this is a space or comma separeted list. So it can be "auth, auth-int" or "auth auth-int". // We will first check the longer value("auth-int") then the short one ("auth"). If one matches we will reset the qop to the exact value. string qop = this.QualityOfProtections != null?this.QualityOfProtections.TrimAndLower() : null; // When we authenticate with a proxy and we want to tunnel the request, we have to use the CONNECT method instead of the // request's, as the proxy will not know about the request itself. string method = isProxy ? "CONNECT" : request.MethodType.ToString().ToUpper(); // When we authenticate with a proxy and we want to tunnel the request, the uri must match what we are sending in the CONNECT request's // Host header. string uri = isProxy ? request.CurrentUri.Host + ":" + request.CurrentUri.Port : request.CurrentUri.GetRequestPathAndQueryURL(); if (qop == null) { string HA2 = string.Concat(request.MethodType.ToString().ToUpper(), ":", request.CurrentUri.GetRequestPathAndQueryURL()).CalculateMD5Hash(); response = string.Format("{0}:{1}:{2}", HA1, Nonce, HA2).CalculateMD5Hash(); } else if (qop.Contains("auth-int")) { qop = "auth-int"; byte[] entityBody = request.GetEntityBody(); if (entityBody == null) { entityBody = VariableSizedBufferPool.NoData; //string.Empty.GetASCIIBytes(); } string HA2 = string.Format("{0}:{1}:{2}", method, uri, entityBody.CalculateMD5Hash()).CalculateMD5Hash(); response = string.Format("{0}:{1}:{2}:{3}:{4}:{5}", HA1, Nonce, ncvalue, cnonce, qop, HA2).CalculateMD5Hash(); } else if (qop.Contains("auth")) { qop = "auth"; string HA2 = string.Concat(method, ":", uri).CalculateMD5Hash(); response = string.Format("{0}:{1}:{2}:{3}:{4}:{5}", HA1, Nonce, ncvalue, cnonce, qop, HA2).CalculateMD5Hash(); } else //throw new NotSupportedException("Unrecognized Quality of Protection value found: " + this.QualityOfProtections); { return(string.Empty); } string result = string.Format("Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", cnonce=\"{4}\", response=\"{5}\"", credentials.UserName, Realm, Nonce, uri, cnonce, response); if (qop != null) { result += String.Concat(", qop=\"", qop, "\", nc=", ncvalue); } if (!string.IsNullOrEmpty(Opaque)) { result = String.Concat(result, ", opaque=\"", Opaque, "\""); } return(result); } // end of case "digest": default: break; } } catch { } return(string.Empty); }