[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] pnetlib/System/Net BasicAuthenticationModule.cs, N
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] pnetlib/System/Net BasicAuthenticationModule.cs, NONE, 1.1 BasicClient.cs, NONE, 1.1 AuthenticationManager.cs, 1.1, 1.2 HttpWebRequest.cs, 1.18, 1.19 |
Date: |
Fri, 14 Nov 2003 05:04:33 +0000 |
Update of /cvsroot/dotgnu-pnet/pnetlib/System/Net
In directory subversions:/tmp/cvs-serv31776/System/Net
Modified Files:
AuthenticationManager.cs HttpWebRequest.cs
Added Files:
BasicAuthenticationModule.cs BasicClient.cs
Log Message:
Implement basic HTTP authentication (patch applied by Rhys).
Index: AuthenticationManager.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System/Net/AuthenticationManager.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** AuthenticationManager.cs 28 Aug 2003 00:25:13 -0000 1.1
--- AuthenticationManager.cs 14 Nov 2003 05:04:31 -0000 1.2
***************
*** 30,33 ****
--- 30,39 ----
private static ArrayList modules;
+ static AuthenticationManager()
+ {
+ /* register the standard modules */
+ Register(new BasicClient());
+ }
+
// Cannot instantiate this class.
private AuthenticationManager() {}
***************
*** 106,110 ****
// Pre-authenticate a request.
- [TODO]
public static Authorization PreAuthenticate
(WebRequest request, ICredentials credentials)
--- 112,115 ----
***************
*** 118,122 ****
return null;
}
! // TODO
return null;
}
--- 123,139 ----
return null;
}
! lock(typeof(AuthenticationManager))
! {
! Authorization auth;
! foreach(IAuthenticationModule module in
ModuleList)
! {
! auth = module.PreAuthenticate
! (request, credentials);
! if(auth != null)
! {
! return auth;
! }
! }
! }
return null;
}
Index: HttpWebRequest.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System/Net/HttpWebRequest.cs,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** HttpWebRequest.cs 12 Nov 2003 04:31:11 -0000 1.18
--- HttpWebRequest.cs 14 Nov 2003 05:04:31 -0000 1.19
***************
*** 69,73 ****
private Stream outStream=null;
private WebResponse response=null;
! private const String format="ddd, dd MMM yyyy HH*:mm:ss GMTzz";//HTTP
internal HttpWebRequest(Uri uri)
--- 69,75 ----
private Stream outStream=null;
private WebResponse response=null;
! private const String format="ddd, dd MMM yyyy HH:mm:ss 'GMT'zz";//HTTP
!
! private HttpController controller=null;
internal HttpWebRequest(Uri uri)
***************
*** 79,82 ****
--- 81,85 ----
this.headers.SetInternal ("Host", uri.Authority);
this.headers.SetInternal ("Date",
DateTime.Now.ToUniversalTime().ToString(format));
+ this.headers.SetInternal ("User-Agent","DotGNU Portable.net");
}
***************
*** 168,171 ****
--- 171,175 ----
if(outStream==null)
{
+ if(preAuthenticate) AddHttpAuthHeaders(null);
outStream=new HttpStream(this);
}
***************
*** 176,191 ****
public override WebResponse GetResponse()
{
if(response!=null) return response;
if(outStream==null)
{
outStream=new HttpStream(this);
outStream.Flush();
// which is the response stream as well
}
! if(this.response==null)
! {
! this.response=new HttpWebResponse(this,this.outStream);
! this.haveResponse=true; // I hope this is correct
! }
(outStream as HttpStream).ContentLength=response.ContentLength;
return this.response;
--- 180,208 ----
public override WebResponse GetResponse()
{
+ HttpWebResponse httpResponse;
+ WebRequest newRequest;
+
if(response!=null) return response;
+
if(outStream==null)
{
+ if(preAuthenticate) AddHttpAuthHeaders(null);
outStream=new HttpStream(this);
outStream.Flush();
// which is the response stream as well
}
!
! httpResponse=new HttpWebResponse(this,this.outStream);
! this.response=httpResponse;
!
! /* here it always is a HttpWebResponse , need to use a Factory
actually
! * When that happens, change the design */
!
! newRequest=Controller.Recurse(this, httpResponse);
!
! /* this is the tricky recursion thing */
! this.response=newRequest.GetResponse();
!
! this.haveResponse=true; // I hope this is correct
(outStream as HttpStream).ContentLength=response.ContentLength;
return this.response;
***************
*** 460,464 ****
}
! public override bool PreAuthenticate
{
get
--- 477,481 ----
}
! public override bool PreAuthenticate
{
get
***************
*** 617,620 ****
--- 634,748 ----
}
+ internal bool AddHttpAuthHeaders(String challenge)
+ {
+ ICredentials cred;
+ String challengeType="Basic"; /* default */
+ Authorization auth;
+
+ if(credentials==null) return false;
+ if(challenge==null && !preAuthenticate)
+ {
+ return false; /* TODO : throw an exception here ? */
+ }
+ else if (challenge!=null)
+ {
+ int len=challenge.IndexOf(' ');
+ challengeType=( len==-1) ? challenge :
+ challenge.Substring(0,len);
+ }
+ cred=credentials.GetCredential(this.Address,challengeType);
+ if(cred==null)
+ {
+ return false; /* TODO : throw an exception here ? */
+ }
+
+ if(preAuthenticate)
+ {
+ auth=AuthenticationManager.PreAuthenticate(this,
+ cred);
+ }
+ else
+ {
+ auth=AuthenticationManager.Authenticate(challenge,
+ this, cred);
+ }
+
+ if(auth==null)
+ {
+ return false; /* TODO : throw an exception here ? */
+ }
+ this.Headers["Authorization"]=auth.Message;
+ return true;
+ }
+
+ internal bool AddProxyAuthHeaders(String challenge)
+ {
+ ICredentials cred;
+ String challengeType="Basic"; /* default */
+ Authorization auth;
+
+ if(proxy==null) return false;
+
+ if(proxy.Credentials==null) return false;
+
+ if(challenge==null)
+ {
+ throw new ArgumentNullException("challenge");
+ }
+ else
+ {
+ int len=challenge.IndexOf(' ');
+ challengeType=( len==-1) ? challenge :
+ challenge.Substring(0,len);
+ }
+
+
cred=proxy.Credentials.GetCredential(this.Address,challengeType);
+
+ if(cred==null)
+ {
+ return false; /* TODO : throw an exception here ? */
+ }
+
+ /* I would have added a PreAuthenticate option for this as well
+ * But MS or ECMA doesn't . So I won't -- Gopal */
+
+ auth=AuthenticationManager.Authenticate(challenge,
+ this, cred);
+ if(auth==null)
+ {
+ return false; /* TODO : throw an exception here ? */
+ }
+
+ this.Headers["Proxy-Authorization"]=auth.Message;
+ return true;
+ }
+
+ /* Re-use an HTTP Webrequest
+ * Note: use with great care ,might be buggy -- Gopal
+ * The basic assumption is that this WebRequest and the stream is of no
further
+ * use. So beware , content will be lost for the last call .
+ * However the response will be retained if it is an incomplete Reset*/
+ internal void ResetRequest()
+ {
+ if(outStream!=null)
+ {
+ /* theoretically I should use the same KeepAlive stream
for subsequent requests
+ * but the HttpStream needs a bit of hacking in that
case */
+ outStream.Close();
+ }
+ headerSent=false;
+ response=null;
+ outStream=null;
+ }
+
+ private HttpController Controller
+ {
+ get
+ {
+ if(controller==null) controller=new
HttpController(this);
+ return this.controller;
+ }
+ }
+
private class HttpStream : Stream
{
***************
*** 651,654 ****
--- 779,783 ----
public override int ReadByte()
{
+ if(contentLength<=0) return -1;
int retval = underlying.ReadByte();
contentLength-=1;
***************
*** 676,679 ****
--- 805,813 ----
}
+ public override void Close()
+ {
+ underlying.Close();
+ }
+
public override bool CanRead
{
***************
*** 755,758 ****
--- 889,893 ----
ProtocolType.Tcp);
server.Connect(ep);
+ /* TODO: Tunnel via Proxy before starting SSL */
return server;
}
***************
*** 764,769 ****
{
#if CONFIG_SSL
- /* TODO: Tunnel via Proxy before starting SSL */
SecureConnection secured=new SecureConnection();
Stream retval=secured.OpenStream(sock);
return retval;
--- 899,904 ----
{
#if CONFIG_SSL
SecureConnection secured=new SecureConnection();
+ /*TODO: suspected memory hold for
SecureConnection */
Stream retval=secured.OpenStream(sock);
return retval;
***************
*** 836,839 ****
--- 971,1085 ----
}
#endif
+
+ /* this class forms the controller of the http life cycle
+ * of OK,Forbiddens and redirects */
+ private class HttpController
+ {
+ /* I know it's a bad practice to have seperate states for each
thing
+ * but I'll fix it later :-) */
+ private enum HttpAuthState
+ {
+ NoAuth,
+ Trying,
+ OK,
+ Failed
+ }
+
+ private HttpAuthState proxy;
+ private HttpAuthState http;
+
+ public HttpController(HttpWebRequest request)
+ {
+ if(request.PreAuthenticate)
+ {
+ this.http=HttpAuthState.Trying;
+ }
+ else
+ {
+ this.http=HttpAuthState.NoAuth;
+ }
+ this.proxy=HttpAuthState.NoAuth;
+ }
+ /* returns this WebRequest or a new one.
+ * If nothing can be done, it will return the same 'ol
+ * request.
+ * Note: will change substantially soon*/
+ public WebRequest Recurse(HttpWebRequest
request,HttpWebResponse response)
+ {
+ HttpStatusCode code=response.StatusCode;
+ switch(code)
+ {
+ case HttpStatusCode.OK:
+ {
+ if(http==HttpAuthState.Trying)
http=HttpAuthState.OK;
+ if(proxy==HttpAuthState.Trying)
proxy=HttpAuthState.OK;
+ return request;
+ }
+ break; /* never reached */
+
+ case HttpStatusCode.ProxyAuthenticationRequired:
+ {
+ String challenge=null;
+
+ if(proxy==HttpAuthState.Trying
|| proxy==HttpAuthState.Failed)
+ {
+
proxy=HttpAuthState.Failed;
+ return request;
+ }
+
challenge=response.Headers["Proxy-Authenticate"];
+ request.ResetRequest();
+
if(request.AddProxyAuthHeaders(challenge))
+ {
+ proxy=HttpAuthState.OK;
+ return request;
+ }
+ else
+ {
+
proxy=HttpAuthState.Failed;
+ return request;
+ }
+ }
+ break;
+
+ case HttpStatusCode.Forbidden:
+ {
+ String challenge=null;
+
+ if(http==HttpAuthState.Trying
|| http==HttpAuthState.Failed)
+ {
+
http=HttpAuthState.Failed;
+ return request;
+ }
+
challenge=response.Headers["WWW-Authenticate"];
+ request.ResetRequest();
+
if(request.AddHttpAuthHeaders(challenge))
+ {
+ http=HttpAuthState.OK;
+ return request;
+ }
+ else
+ {
+
http=HttpAuthState.Failed;
+ return request;
+ }
+ }
+ break;
+
+ case HttpStatusCode.Redirect:
+ {
+ /* TODO */
+ }
+ break;
+
+ }
+
+ return request;
+ }
+
+ public override String ToString()
+ {
+ return
"(Proxy="+proxy.ToString()+",Http="+http.ToString()+")";
+ }
+ }
}//class
--- NEW FILE: BasicAuthenticationModule.cs ---
/*
* BasicAuthenticationModule.cs - Implementation of the
* "System.Net.BasicAuthenticationModule" class.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace System.Net
{
using System;
using System.Text;
internal class BasicAuthenticationModule : IAuthenticationModule
{
// Authenticate a challenge from the server.
public Authorization Authenticate
(String challenge, WebRequest request, ICredentials credentials)
{
if(credentials==null || challenge==null || request==null
|| (!challenge.ToLower().StartsWith("basic")))
{
return null;
}
return AuthenticateInternal(request, credentials);
}
// Pre-authenticate a request.
public Authorization PreAuthenticate
(WebRequest request, ICredentials credentials)
{
if(request==null || credentials==null)
{
return null;
}
return AuthenticateInternal(request, credentials);
}
private Authorization AuthenticateInternal(WebRequest request,
ICredentials credentials)
{
String user,password,domain;
NetworkCredential netcredentials=credentials.GetCredential(
request.RequestUri, "Basic");
user=netcredentials.UserName;
password=netcredentials.Password;
domain=netcredentials.Domain;
String response=((domain==null || domain=="") ? "" :
(domain + "\\"))
+ user + ":" + password;
byte[] buf=Encoding.Default.GetBytes(response);
return new Authorization("Basic "+Convert.ToBase64String(buf));
}
// Get the authentiation type supported by this module.
public String AuthenticationType
{
get
{
return "Basic";
}
}
// Determine if this module supports pre-authentication.
public bool CanPreAuthenticate
{
get
{
return true;
}
}
}; // interface IAuthenticationModule
}; // namespace System.Net
--- NEW FILE: BasicClient.cs ---
/*
* BasicClient.cs - Implementation of the
* "System.Net.BasicClient" class.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace System.Net
{
using System;
using System.Text;
internal class BasicClient : IAuthenticationModule
{
// Authenticate a challenge from the server.
public Authorization Authenticate
(String challenge, WebRequest request, ICredentials credentials)
{
if(credentials==null || challenge==null || request==null
|| (!challenge.ToLower().StartsWith("basic")))
{
return null;
}
return AuthenticateInternal(request, credentials);
}
// Pre-authenticate a request.
public Authorization PreAuthenticate
(WebRequest request, ICredentials credentials)
{
if(request==null || credentials==null)
{
return null;
}
return AuthenticateInternal(request, credentials);
}
private Authorization AuthenticateInternal(WebRequest request,
ICredentials credentials)
{
String user,password,domain;
NetworkCredential netcredentials=credentials.GetCredential(
request.RequestUri, "Basic");
user=netcredentials.UserName;
password=netcredentials.Password;
domain=netcredentials.Domain;
String response=((domain==null || domain=="") ? "" :
(domain + "\\"))
+ user + ":" + password;
byte[] buf=Encoding.Default.GetBytes(response);
return new Authorization("Basic "+Convert.ToBase64String(buf));
}
// Get the authentiation type supported by this module.
public String AuthenticationType
{
get
{
return "Basic";
}
}
// Determine if this module supports pre-authentication.
public bool CanPreAuthenticate
{
get
{
return true;
}
}
}; // class BasicClient
}; // namespace System.Net
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] pnetlib/System/Net BasicAuthenticationModule.cs, NONE, 1.1 BasicClient.cs, NONE, 1.1 AuthenticationManager.cs, 1.1, 1.2 HttpWebRequest.cs, 1.18, 1.19,
Rhys Weatherley <address@hidden> <=