/// <summary> /// Initializes a new instance of the <see cref = "CosignServer" /> class. /// </summary> /// <param name = "serverIp">The server ip address.</param> /// <param name = "cosignConfig">The cosign config.</param> /// <exception cref="Exception">Unable to view the certificate store</exception> public CosignServer(IPAddress serverIp, CosignConfiguration cosignConfig) { ServerIpAddress = serverIp; _serverPort = cosignConfig.CosignServerPort; _serverName = cosignConfig.CosignServerName; _cosignServiceName = cosignConfig.ServiceName; // Get server certificate from the store try { var certificateStore = new X509Store(StoreName.My, StoreLocation.LocalMachine); certificateStore.Open(OpenFlags.ReadOnly); _certificateCollection = certificateStore.Certificates.Find(X509FindType.FindBySubjectName, cosignConfig.CertCommonName, true); } catch (Exception ex) { _logger.Fatal("Unable to view the certificate store", ex); throw new Exception("Unable to view the certificate store", ex); } }
/// <summary> /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see /// cref = "T:System.Web.IHttpHandler" /> interface. /// </summary> /// <param name = "context">An <see cref = "T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> /// <exception cref="HttpException">Internal Server Error</exception> public void ProcessRequest(HttpContext context) { CosignConfiguration cosignConfig; CurrentLogger.Trace("ProcessRequest of handler started"); try { CurrentLogger.Trace("Loading configuration"); cosignConfig = new CosignConfiguration(); } catch (Exception ex) { CurrentLogger.Fatal("Cosign Configuration Invalid", ex); throw new HttpException(500, "Internal Server Error", ex); } CurrentLogger.Trace("Raw URL received {0}", context.Request.RawUrl); if (context.Request.QueryString.Count < 2) { CurrentLogger.Error("Invalid query string passed to the handler"); throw new HttpException(403, "Forbidden"); } if (!string.IsNullOrEmpty(context.Request.QueryString[cosignConfig.ServiceName])) { string serviceCookieValue = context.Server.UrlEncode(context.Request.QueryString[cosignConfig.ServiceName]); string redirectUrl = context.Request.RawUrl.Substring(context.Request.RawUrl.IndexOf("&", StringComparison.Ordinal) + 1); CurrentLogger.Trace("ServiceCookie Value:{0}", serviceCookieValue); CurrentLogger.Trace("RedirectURL Value:{0}", redirectUrl); if (serviceCookieValue != null && serviceCookieValue.Length < 120) { CurrentLogger.Error("Invalid Cookie Length"); throw new HttpException(400, "Bad Request"); } if (!Regex.IsMatch(redirectUrl, cosignConfig.ValidReference)) { CurrentLogger.Error("Destination of {0} does not match {1}", redirectUrl, cosignConfig.ValidReference); context.Response.Redirect(cosignConfig.CosignErrorUrl, true); } // Retries to all servers int retries = 0; bool fatalErrorOrFound = false; var cosignCookie = new CosignCookie(); while (retries < cosignConfig.ServerRetries && fatalErrorOrFound == false) { CurrentLogger.Trace("Trying to validate cookie retry - {0}", retries); try { cosignCookie = Connection.ConnectAndValidate(serviceCookieValue, false, cosignConfig); } catch (Exception ex) { CurrentLogger.Fatal("Exception while validating the cookie", ex); throw new HttpException(500, "Internal Server Error", ex); } switch (cosignCookie.ErrorCode) { case CosignGlobals.CosignLoggedOut: CurrentLogger.Trace("User is already logged out, redirecting to login"); context.Response.Redirect(cosignConfig.CosignServerUrl + cosignConfig.ServiceName + "&" + redirectUrl, true); break; case CosignGlobals.CosignError: case CosignGlobals.CosignLoggedIn: fatalErrorOrFound = true; break; } retries++; } if (cosignCookie.ErrorCode == CosignGlobals.CosignLoggedIn) { CurrentLogger.Info("Client ip address, Forwarded Address - {0} , {1}", context.Request.UserHostAddress, context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]); ////if (context.Request.UserHostAddress == cosignCookie.ClientIpAddress) ////{ CurrentLogger.Trace("Cosign cookie found and validated"); var cookie = new HttpCookie(cosignConfig.ServiceName, serviceCookieValue) { Secure = cosignConfig.SecureCookies, HttpOnly = cosignConfig.HttpOnlyCookies }; CurrentLogger.Trace("Cookie has been set with the value {0}", serviceCookieValue); context.Response.Cookies.Set(cookie); CurrentLogger.Trace("Redirecting client to {0}", redirectUrl); context.Response.Redirect(redirectUrl); ////} ////else ////{ ////logger.Warn("Client ip address is different than the cookie - {0} , {1}, {2}", serviceCookieValue, context.Request.UserHostAddress, context.Request.ServerVariables["REMOTE_ADDR"]); ////context.Response.Redirect(cosignConfig.CosignServerUrl + cosignConfig.ServiceName + "&" + redirectUrl, true); ////} } else if (cosignCookie.ErrorCode == CosignGlobals.CosignRetry) { CurrentLogger.Warn("Cookie was not found in db, try again to authenticate"); context.Response.Redirect( cosignConfig.CosignServerUrl + cosignConfig.ServiceName + "&" + redirectUrl, true); } else { CurrentLogger.Fatal("An Error has occurred that prevents cosign doing anything further - {0}", cosignCookie.ErrorMessage); throw new HttpException(503, "Service Unavailable"); } } else { CurrentLogger.Error("Bad Service Name"); } CurrentLogger.Error("Bad Request, fell out the bottom"); throw new HttpException(400, "Bad Request"); }
/// <summary> Connects to the cosign server and validates the serviceCookie value. </summary> /// <remarks> Chris Motch, 9/23/2011. </remarks> /// <exception cref="Exception"> Thrown when an exception error condition occurs. </exception> /// <param name="serviceCookieValue"> The service cookie value. </param> /// <param name="writeCookie"> if set to <c>true</c> write the cookie file to the file /// cache. </param> /// <param name="cosignConfig"> The cosign config. </param> /// <returns>A valid cosign cookie</returns> public CosignCookie ConnectAndValidate(string serviceCookieValue, bool writeCookie, CosignConfiguration cosignConfig) { Logger logger = GlobalLogger.Instance.GetLogger("CosignConnection"); CosignCookie cosignCookie = null; if (_serverList != null) { foreach (CosignServer server in _serverList) { logger.Trace("Checking to see if server connection is alive for server : {0}", server.ServerIpAddress); if (server.CheckAlive()) { cosignCookie = server.CheckCookie(serviceCookieValue); if (cosignCookie.ErrorCode == CosignGlobals.CosignError) { server.CloseConnection(); } else if (cosignCookie.ErrorCode == CosignGlobals.CosignLoggedIn) { break; } } } } if (cosignCookie == null) { // Either there were no existing connections, or all the existing connections failed _serverList = new List<CosignServer>(); logger.Trace("Getting ip address for cosign server {0}", cosignConfig.CosignServerName); IPAddress[] addresslist = Dns.GetHostAddresses(cosignConfig.CosignServerName); logger.Trace("Number of ip address from DNS host name : {0}", addresslist.Length); foreach (IPAddress theaddress in addresslist) { logger.Trace("Initiating secure connection with cosign server - {0}", theaddress); CosignServer cosignServer; try { cosignServer = new CosignServer(theaddress, cosignConfig); } catch (Exception ex) { logger.Fatal("Unable to to create cosign server object", ex); throw new Exception("Unable to create cosign server object", ex); } if (cosignServer.EstablishConnection()) { logger.Trace("Secure connection established with cosign server - {0}", theaddress); logger.Trace("Checking cosign cookie {0},{1}", serviceCookieValue, cosignConfig.ServiceName); _serverList.Add(cosignServer); cosignCookie = cosignServer.CheckCookie(serviceCookieValue); if (cosignCookie.ErrorCode == CosignGlobals.CosignLoggedIn) { break; } logger.Warn("Response from Cosign server indicated a problem - {0}", cosignCookie.ErrorMessage); } else { logger.Error("Could not initiate secure connection with cosign server - {0}", theaddress); } } } if (cosignCookie != null && cosignCookie.ErrorCode == CosignGlobals.CosignLoggedIn) { logger.Trace("Cookie found, writing to cache - {0},{1}", writeCookie, cosignCookie.ErrorMessage); if (writeCookie) { cosignCookie.SaveCookie(cosignConfig.CookieDb + "\\" + serviceCookieValue); //// Do something with the kerb ticket, stick it in the return cookie or something //// Byte[] tgtTicket=cosignSsl.RetrieveKerberosTicket(serviceCookieValue, cosignConfig.ServiceName,cosignConfig.KerbDBPath); } } // We have our cookie and its valid, lets get out of here return cosignCookie; }