dotgnu-pnet-commits
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]