// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+using MonoSecurity::Mono.Security.Interface;
+#else
+using Mono.Security.Interface;
+#endif
+#endif
+
using System;
using System.Collections;
using System.Configuration;
using System.Net;
using System.Net.Cache;
using System.Net.Sockets;
+using System.Net.Security;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
+using Mono.Net.Security;
namespace System.Net
{
int maxResponseHeadersLength;
static int defaultMaxResponseHeadersLength;
int readWriteTimeout = 300000; // ms
+ IMonoTlsProvider tlsProvider;
+#if SECURITY_DEP
+ MonoTlsSettings tlsSettings;
+#endif
+ ServerCertValidationCallback certValidationCallback;
enum NtlmAuthState {
None,
AuthorizationState auth_state, proxy_auth_state;
string host;
+ [NonSerialized]
+ internal Action<Stream> ResendContentFactory;
+
// Constructors
static HttpWebRequest ()
{
{
this.requestUri = uri;
this.actualUri = uri;
- this.proxy = GlobalProxySelection.Select;
- this.webHeaders = new WebHeaderCollection (WebHeaderCollection.HeaderInfo.Request);
+ this.proxy = InternalDefaultWebProxy;
+ this.webHeaders = new WebHeaderCollection (WebHeaderCollectionType.HttpWebRequest);
ThrowOnError = true;
ResetAuthorization ();
}
+
+#if SECURITY_DEP
+ internal HttpWebRequest (Uri uri, IMonoTlsProvider tlsProvider, MonoTlsSettings settings = null)
+ : this (uri)
+ {
+ this.tlsProvider = tlsProvider;
+ this.tlsSettings = settings;
+ }
+#endif
[Obsolete ("Serialization is obsoleted for this type", false)]
protected HttpWebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
// Properties
+ void SetSpecialHeaders(string HeaderName, string value) {
+ value = WebHeaderCollection.CheckBadChars(value, true);
+ webHeaders.RemoveInternal(HeaderName);
+ if (value.Length != 0) {
+ webHeaders.AddInternal(HeaderName, value);
+ }
+ }
+
public string Accept {
get { return webHeaders ["Accept"]; }
set {
CheckRequestStarted ();
- webHeaders.RemoveAndAdd ("Accept", value);
+ SetSpecialHeaders ("Accept", value);
}
}
internal bool InternalAllowBuffering {
get {
- return (allowBuffering && (method != "HEAD" && method != "GET" &&
- method != "MKCOL" && method != "CONNECT" &&
- method != "TRACE"));
+ return allowBuffering && MethodWithBuffer;
}
}
+
+ bool MethodWithBuffer {
+ get {
+ return method != "HEAD" && method != "GET" &&
+ method != "MKCOL" && method != "CONNECT" &&
+ method != "TRACE";
+ }
+ }
+
+ internal IMonoTlsProvider TlsProvider {
+ get { return tlsProvider; }
+ }
+
+#if SECURITY_DEP
+ internal MonoTlsSettings TlsSettings {
+ get { return tlsSettings; }
+ }
+#endif
public X509CertificateCollection ClientCertificates {
get {
if (certificates == null)
certificates = new X509CertificateCollection ();
-
return certificates;
}
- [MonoTODO]
set {
- throw GetMustImplement ();
+ if (value == null)
+ throw new ArgumentNullException ("value");
+ certificates = value;
}
}
-
+
public string Connection {
get { return webHeaders ["Connection"]; }
set {
if (keepAlive)
value = value + ", Keep-Alive";
- webHeaders.RemoveAndAdd ("Connection", value);
+ webHeaders.CheckUpdate ("Connection", value);
}
}
public override string ContentType {
get { return webHeaders ["Content-Type"]; }
set {
- if (value == null || value.Trim().Length == 0) {
- webHeaders.RemoveInternal ("Content-Type");
- return;
- }
- webHeaders.RemoveAndAdd ("Content-Type", value);
+ SetSpecialHeaders ("Content-Type", value);
}
}
return DateTime.ParseExact (date, "r", CultureInfo.InvariantCulture).ToLocalTime ();
}
set {
- if (value.Equals (DateTime.MinValue))
- webHeaders.RemoveInternal ("Date");
- else
- webHeaders.RemoveAndAdd ("Date", value.ToUniversalTime ().ToString ("r", CultureInfo.InvariantCulture));
+ SetDateHeaderHelper ("Date", value);
}
}
+ void SetDateHeaderHelper(string headerName, DateTime dateTime) {
+ if (dateTime == DateTime.MinValue)
+ SetSpecialHeaders(headerName, null); // remove header
+ else
+ SetSpecialHeaders(headerName, HttpProtocolUtils.date2string(dateTime));
+ }
+
#if !NET_2_1
[MonoTODO]
public static new RequestCachePolicy DefaultCachePolicy
if (val == "100-continue")
throw new ArgumentException ("100-Continue cannot be set with this property.",
"value");
- webHeaders.RemoveAndAdd ("Expect", value);
+
+ webHeaders.CheckUpdate ("Expect", value);
}
}
get { return webHeaders; }
set {
CheckRequestStarted ();
- WebHeaderCollection newHeaders = new WebHeaderCollection (WebHeaderCollection.HeaderInfo.Request);
- int count = value.Count;
- for (int i = 0; i < count; i++)
- newHeaders.Add (value.GetKey (i), value.Get (i));
- webHeaders = newHeaders;
+ WebHeaderCollection webHeaders = value;
+ WebHeaderCollection newWebHeaders = new WebHeaderCollection(WebHeaderCollectionType.HttpWebRequest);
+
+ // Copy And Validate -
+ // Handle the case where their object tries to change
+ // name, value pairs after they call set, so therefore,
+ // we need to clone their headers.
+ //
+
+ foreach (String headerName in webHeaders.AllKeys ) {
+ newWebHeaders.Add(headerName,webHeaders[headerName]);
+ }
+
+ webHeaders = newWebHeaders;
}
}
CheckRequestStarted ();
proxy = value;
servicePoint = null; // we may need a new one
+ GetServicePoint ();
}
}
if (!sendChunked)
throw new ArgumentException ("SendChunked must be True", "value");
- webHeaders.RemoveAndAdd ("Transfer-Encoding", value);
+ webHeaders.CheckUpdate ("Transfer-Encoding", value);
}
}
internal bool ProxyQuery {
get { return servicePoint.UsesProxy && !servicePoint.UseConnect; }
}
-
+
+ internal ServerCertValidationCallback ServerCertValidationCallback {
+ get { return certValidationCallback; }
+ }
+
+ public RemoteCertificateValidationCallback ServerCertificateValidationCallback {
+ get {
+ if (certValidationCallback == null)
+ return null;
+ return certValidationCallback.ValidationCallback;
+ }
+ set
+ {
+ if (value == null)
+ certValidationCallback = null;
+ else
+ certValidationCallback = new ServerCertValidationCallback (value);
+ }
+ }
+
// Methods
internal ServicePoint GetServicePoint ()
{
if (rangeSpecifier == null)
throw new ArgumentNullException ("rangeSpecifier");
- if (!WebHeaderCollection.IsHeaderValue (rangeSpecifier))
+ if (!WebHeaderCollection.IsValidToken (rangeSpecifier))
throw new ArgumentException ("Invalid range specifier", "rangeSpecifier");
string r = webHeaders ["Range"];
r = r + "0" + n;
else
r = r + n + "-";
- webHeaders.RemoveAndAdd ("Range", r);
+ webHeaders.ChangeInternal ("Range", r);
}
public
{
if (rangeSpecifier == null)
throw new ArgumentNullException ("rangeSpecifier");
- if (!WebHeaderCollection.IsHeaderValue (rangeSpecifier))
+ if (!WebHeaderCollection.IsValidToken (rangeSpecifier))
throw new ArgumentException ("Invalid range specifier", "rangeSpecifier");
if (from > to || from < 0)
throw new ArgumentOutOfRangeException ("from");
r += ",";
r = String.Format ("{0}{1}-{2}", r, from, to);
- webHeaders.RemoveAndAdd ("Range", r);
+ webHeaders.ChangeInternal ("Range", r);
}
}
}
- if (!requestSent) {
+ if (requestSent)
+ return;
+
+ try {
requestSent = true;
redirects = 0;
servicePoint = GetServicePoint ();
abortHandler = servicePoint.SendRequest (this, connectionGroup);
+ } catch (Exception ex) {
+ aread.SetCompleted (synch, ex);
+ aread.DoCallback ();
}
});
if (e != null)
throw e;
- if (AllowWriteStreamBuffering)
+ if (AllowWriteStreamBuffering || method == "GET")
contentLength = -1;
uriString = webResponse.Headers ["Location"];
bool continue100 = false;
if (sendChunked) {
continue100 = true;
- webHeaders.RemoveAndAdd ("Transfer-Encoding", "chunked");
+ webHeaders.ChangeInternal ("Transfer-Encoding", "chunked");
webHeaders.RemoveInternal ("Content-Length");
} else if (contentLength != -1) {
if (auth_state.NtlmAuthState == NtlmAuthState.Challenge || proxy_auth_state.NtlmAuthState == NtlmAuthState.Challenge) {
if (actualVersion == HttpVersion.Version11 && continue100 &&
servicePoint.SendContinue) { // RFC2616 8.2.3
- webHeaders.RemoveAndAdd ("Expect" , "100-continue");
+ webHeaders.ChangeInternal ("Expect" , "100-continue");
expectContinue = true;
} else {
webHeaders.RemoveInternal ("Expect");
if (keepAlive && (version == HttpVersion.Version10 || spoint10)) {
if (webHeaders[connectionHeader] == null
|| webHeaders[connectionHeader].IndexOf ("keep-alive", StringComparison.OrdinalIgnoreCase) == -1)
- webHeaders.RemoveAndAdd (connectionHeader, "keep-alive");
+ webHeaders.ChangeInternal (connectionHeader, "keep-alive");
} else if (!keepAlive && version == HttpVersion.Version11) {
- webHeaders.RemoveAndAdd (connectionHeader, "close");
+ webHeaders.ChangeInternal (connectionHeader, "close");
}
webHeaders.SetInternal ("Host", Host);
if (cookieContainer != null) {
string cookieHeader = cookieContainer.GetCookieHeader (actualUri);
if (cookieHeader != "")
- webHeaders.RemoveAndAdd ("Cookie", cookieHeader);
+ webHeaders.ChangeInternal ("Cookie", cookieHeader);
else
webHeaders.RemoveInternal ("Cookie");
}
if ((auto_decomp & DecompressionMethods.Deflate) != 0)
accept_encoding = accept_encoding != null ? "gzip, deflate" : "deflate";
if (accept_encoding != null)
- webHeaders.RemoveAndAdd ("Accept-Encoding", accept_encoding);
+ webHeaders.ChangeInternal ("Accept-Encoding", accept_encoding);
if (!usedPreAuth && preAuthenticate)
DoPreAuthenticate ();
wex = new WebException (msg, status);
} else {
msg = String.Format ("Error: {0} ({1})", status, exc.Message);
- wex = new WebException (msg, exc, status);
+ wex = new WebException (msg, status, WebExceptionInternalStatus.RequestFatal, exc);
}
r.SetCompleted (false, wex);
r.DoCallback ();
bodyBuffer = null;
writeStream.Close ();
}
- } else if (method != "HEAD" && method != "GET" && method != "MKCOL" && method != "CONNECT" &&
- method != "TRACE") {
+ } else if (MethodWithBuffer) {
if (getResponseCalled && !writeStream.RequestWritten)
return writeStream.WriteRequestAsync (result);
}
if (wce != null) {
WebConnection cnc = wce.Connection;
cnc.PriorityRequest = this;
- ICredentials creds = !isProxy ? credentials : proxy.Credentials;
+ ICredentials creds = (!isProxy || proxy == null) ? credentials : proxy.Credentials;
if (creds != null) {
cnc.NtlmCredential = creds.GetCredential (requestUri, "NTLM");
cnc.UnsafeAuthenticatedConnectionSharing = unsafe_auth_blah;
return;
}
- bool isProxy = ProxyQuery && !proxy.IsBypassed (actualUri);
+ bool isProxy = ProxyQuery && proxy != null && !proxy.IsBypassed (actualUri);
bool redirected;
try {
if (isProxy && (request.proxy == null || request.proxy.Credentials == null))
return false;
- string [] authHeaders = response.Headers.GetValues_internal (isProxy ? "Proxy-Authenticate" : "WWW-Authenticate", false);
+ string [] authHeaders = response.Headers.GetValues (isProxy ? "Proxy-Authenticate" : "WWW-Authenticate");
if (authHeaders == null || authHeaders.Length == 0)
return false;
return false;
request.webHeaders [isProxy ? "Proxy-Authorization" : "Authorization"] = auth.Message;
isCompleted = auth.Complete;
- bool is_ntlm = (auth.Module.AuthenticationType == "NTLM");
+ bool is_ntlm = (auth.ModuleAuthenticationType == "NTLM");
if (is_ntlm)
ntlm_auth_state = (NtlmAuthState)((int) ntlm_auth_state + 1);
return true;
(ProxyQuery && !proxy_auth_state.IsCompleted && code == HttpStatusCode.ProxyAuthenticationRequired)) {
if (!usedPreAuth && CheckAuthorization (webResponse, code)) {
// Keep the written body, so it can be rewritten in the retry
- if (InternalAllowBuffering) {
- if (writeStream.WriteBufferLength > 0) {
- bodyBuffer = writeStream.WriteBuffer;
- bodyBufferLength = writeStream.WriteBufferLength;
+ if (MethodWithBuffer) {
+ if (AllowWriteStreamBuffering) {
+ if (writeStream.WriteBufferLength > 0) {
+ bodyBuffer = writeStream.WriteBuffer;
+ bodyBufferLength = writeStream.WriteBufferLength;
+ }
+
+ return true;
+ }
+
+ //
+ // Buffering is not allowed but we have alternative way to get same content (we
+ // need to resent it due to NTLM Authentication).
+ //
+ if (ResendContentFactory != null) {
+ using (var ms = new MemoryStream ()) {
+ ResendContentFactory (ms);
+ bodyBuffer = ms.ToArray ();
+ bodyBufferLength = bodyBuffer.Length;
+ }
+ return true;
}
- return true;
} else if (method != "PUT" && method != "POST") {
bodyBuffer = null;
return true;