2002-12-18 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.Security / FormsAuthentication.cs
1 //
2 // System.Web.Security.FormsAuthentication
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002 Ximian, Inc (http://www.ximian.com)
8 //
9
10 using System;
11 using System.Collections;
12 using System.Security.Cryptography;
13 using System.Text;
14 using System.Web;
15 using System.Web.Configuration;
16 using System.Web.Util;
17
18 namespace System.Web.Security
19 {
20         public sealed class FormsAuthentication
21         {
22                 static string authConfigPath = "system.web/authentication";
23                 static bool initialized;
24                 static string cookieName;
25                 static string cookiePath;
26                 static int timeout;
27                 static FormsProtectionEnum protection;
28
29                 public static bool Authenticate (string name, string password)
30                 {
31                         if (name == null || password == null)
32                                 return false;
33
34                         Initialize ();
35                         HttpContext context = HttpContext.Current;
36                         if (context == null)
37                                 throw new HttpException ("Context is null!");
38
39                         AuthConfig config = context.GetConfig (authConfigPath) as AuthConfig;
40                         Hashtable users = config.CredentialUsers;
41                         string stored = users [name] as string;
42                         if (stored == null)
43                                 return false;
44
45                         switch (config.PasswordFormat) {
46                         case FormsAuthPasswordFormat.Clear:
47                                 /* Do nothing */
48                                 break;
49                         case FormsAuthPasswordFormat.MD5:
50                                 stored = HashPasswordForStoringInConfigFile (stored, "MD5");
51                                 break;
52                         case FormsAuthPasswordFormat.SHA1:
53                                 stored = HashPasswordForStoringInConfigFile (stored, "SHA1");
54                                 break;
55                         }
56
57                         return (password == stored);
58                 }
59
60                 public static FormsAuthenticationTicket Decrypt (string encryptedTicket)
61                 {
62                         if (encryptedTicket == null || encryptedTicket == String.Empty)
63                                 throw new ArgumentException ("Invalid encrypted ticket", "encryptedTicket");
64
65                         Initialize ();
66                         byte [] bytes = MachineKeyConfigHandler.GetBytes (encryptedTicket, encryptedTicket.Length);
67                         //TODO: decrypt
68                         string decrypted = WebEncoding.Encoding.GetString (bytes);
69                         FormsAuthenticationTicket ticket = null;
70                         try {
71                                 string [] values = decrypted.Split ((char) 1, (char) 2, (char) 3, (char) 4, (char) 5, (char) 6, (char) 7);
72                                 if (values.Length != 8)
73                                         throw new Exception (values.Length + " " + encryptedTicket);
74
75                                 ticket = new FormsAuthenticationTicket (Int32.Parse (values [0]),
76                                                                         values [1],
77                                                                         new DateTime (Int64.Parse (values [2])),
78                                                                         new DateTime (Int64.Parse (values [3])),
79                                                                         (values [4] == "1"),
80                                                                         values [5],
81                                                                         values [6]);
82                         } catch (Exception e) {
83                                 throw new ArgumentException ("Invalid encrypted ticket", "encryptedTicket", e);
84                         }
85
86                         return ticket;
87                 }
88
89                 public static string Encrypt (FormsAuthenticationTicket ticket)
90                 {
91                         if (ticket == null)
92                                 throw new ArgumentNullException ("ticket");
93
94                         Initialize ();
95                         StringBuilder allTicket = new StringBuilder ();
96                         allTicket.Append (ticket.Version);
97                         allTicket.Append ('\u0001');
98                         allTicket.Append (ticket.Name);
99                         allTicket.Append ('\u0002');
100                         allTicket.Append (ticket.IssueDate.Ticks);
101                         allTicket.Append ('\u0003');
102                         allTicket.Append (ticket.Expiration.Ticks);
103                         allTicket.Append ('\u0004');
104                         allTicket.Append (ticket.IsPersistent ? '1' : '0');
105                         allTicket.Append ('\u0005');
106                         allTicket.Append (ticket.UserData);
107                         allTicket.Append ('\u0006');
108                         allTicket.Append (ticket.CookiePath);
109                         allTicket.Append ('\u0007');
110                         //if (protection == FormsProtectionEnum.None)
111                                 return GetHexString (allTicket.ToString ());
112                         //TODO: encrypt and validate
113                 }
114
115                 public static HttpCookie GetAuthCookie (string userName, bool createPersistentCookie)
116                 {
117                         return GetAuthCookie (userName, createPersistentCookie, cookiePath);
118                 }
119
120                 public static HttpCookie GetAuthCookie (string userName, bool createPersistentCookie, string strCookiePath)
121                 {
122                         Initialize ();
123
124                         if (userName == null)
125                                 userName = String.Empty;
126
127                         if (strCookiePath == null || strCookiePath.Length == 0)
128                                 strCookiePath = cookiePath;
129
130                         DateTime now = DateTime.Now;
131                         DateTime then;
132                         if (createPersistentCookie)
133                                 then = now.AddYears (50);
134                         else
135                                 then = now.AddMinutes (timeout);
136
137                         FormsAuthenticationTicket ticket = new FormsAuthenticationTicket (1,
138                                                                                           userName,
139                                                                                           now,
140                                                                                           then,
141                                                                                           createPersistentCookie,
142                                                                                           String.Empty,
143                                                                                           cookiePath);
144
145                         if (!createPersistentCookie)
146                                 then = DateTime.MinValue;
147
148                         return new HttpCookie (cookieName, Encrypt (ticket), strCookiePath, then);
149                 }
150
151                 [MonoTODO]
152                 public static string GetRedirectUrl (string userName, bool createPersistentCookie)
153                 {
154                         throw new NotImplementedException ();
155                 }
156
157                 static string GetHexString (string str)
158                 {
159                         return GetHexString (WebEncoding.Encoding.GetBytes (str));
160                 }
161
162                 static string GetHexString (byte [] bytes)
163                 {
164                         StringBuilder result = new StringBuilder (bytes.Length * 2);
165                         foreach (byte b in bytes)
166                                 result.AppendFormat ("{0:x2}", (int) b);
167
168                         return result.ToString ();
169                 }
170
171                 public static string HashPasswordForStoringInConfigFile (string password, string passwordFormat)
172                 {
173                         if (password == null)
174                                 throw new ArgumentNullException ("password");
175
176                         if (passwordFormat == null)
177                                 throw new ArgumentNullException ("passwordFormat");
178
179                         byte [] bytes;
180                         if (String.Compare (passwordFormat, "MD5", true) == 0) {
181                                 bytes = MD5.Create ().ComputeHash (WebEncoding.Encoding.GetBytes (password));
182                         } else if (String.Compare (passwordFormat, "SHA1", true) == 0) {
183                                 bytes = SHA1.Create ().ComputeHash (WebEncoding.Encoding.GetBytes (password));
184                         } else {
185                                 throw new ArgumentException ("The format must be either MD5 or SHA1", "passwordFormat");
186                         }
187
188                         return GetHexString (bytes);
189                 }
190
191                 public static void Initialize ()
192                 {
193                         if (initialized)
194                                 return;
195
196                         lock (typeof (FormsAuthentication)) {
197                                 if (initialized)
198                                         return;
199
200                                 HttpContext context = HttpContext.Current;
201                                 if (context == null)
202                                         throw new HttpException ("Context is null!");
203
204                                 AuthConfig authConfig = context.GetConfig (authConfigPath) as AuthConfig;
205                                 if (authConfig != null) {
206                                         cookieName = authConfig.CookieName;
207                                         timeout = authConfig.Timeout;
208                                         cookiePath = authConfig.CookiePath;
209                                         protection = authConfig.Protection;
210                                 } else {
211                                         cookieName = ".MONOAUTH";
212                                         timeout = 30;
213                                         cookiePath = "/";
214                                         protection = FormsProtectionEnum.All;
215                                 }
216
217                                 initialized = true;
218                         }
219                 }
220
221                 [MonoTODO]
222                 public static void RedirectFromLoginPage (string userName, bool createPersistentCookie)
223                 {
224                         throw new NotImplementedException ();
225                 }
226
227                 [MonoTODO]
228                 public static void RedirectFromLoginPage (string userName, bool createPersistentCookie, string strCookiePath)
229                 {
230                         throw new NotImplementedException ();
231                 }
232                 [MonoTODO]
233                 public static FormsAuthenticationTicket RenewTicketIfOld (FormsAuthenticationTicket tOld)
234                 {
235                         throw new NotImplementedException ();
236                 }
237
238                 public static void SetAuthCookie (string userName, bool createPersistentCookie)
239                 {
240                         SetAuthCookie (userName, createPersistentCookie, cookiePath);
241                 }
242
243                 public static void SetAuthCookie (string userName, bool createPersistentCookie, string strCookiePath)
244                 {
245                         HttpContext context = HttpContext.Current;
246                         if (context == null)
247                                 throw new HttpException ("Context is null!");
248
249                         HttpResponse response = context.Response;
250                         if (response == null)
251                                 throw new HttpException ("Response is null!");
252
253                         response.Cookies.Add (GetAuthCookie (userName, createPersistentCookie, strCookiePath));
254                 }
255
256                 public static void SignOut ()
257                 {
258                         Initialize ();
259
260                         HttpContext context = HttpContext.Current;
261                         if (context == null)
262                                 throw new HttpException ("Context is null!");
263
264                         HttpResponse response = context.Response;
265                         if (response == null)
266                                 throw new HttpException ("Response is null!");
267
268                         response.Cookies.MakeCookieExpire (cookieName, cookiePath);
269                 }
270
271                 public static string FormsCookieName
272                 {
273                         get {
274                                 Initialize ();
275                                 return cookieName;
276                         }
277                 }
278
279                 public static string FormsCookiePath
280                 {
281                         get {
282                                 Initialize ();
283                                 return cookiePath;
284                         }
285                 }
286         }
287 }
288