/// <summary> /// Removes an association from the associations table. /// </summary> /// <param name="assoc">Association to remove from persistence.</param> public void Remove(Association assoc) { DataRow[] rows = Associations.Select("handle = '" + assoc.Handle + "'"); foreach (DataRow dr in rows) { Associations.Rows.Remove(dr); } Associations.AcceptChanges(); }
/// <summary> /// Removes an association from the database. /// </summary> /// <param name="assoc">Association to remove.</param> public void Remove(Association assoc) { string sql = "DELETE FROM " + _tableName + " WHERE Handle = '" + FixSqlIn(assoc.Handle) + "'"; _conn.Open(); IDbCommand comm = _conn.CreateCommand(); comm.CommandText = sql; comm.ExecuteNonQuery(); _conn.Close(); }
/// <summary> /// Adds a new association to the associations table. /// </summary> /// <param name="association">The association entry to store.</param> public void Add(Association association) { // Check for existing association DataRow[] result = Associations.Select("server = '" + association.Server + "'"); if (result.Length > 0) { for (int i = 0; i < result.Length; i++) { Associations.Rows.Remove(result[i]); } } // Add new row DataRow dr = Associations.NewRow(); dr["protocol"] = association.ProtocolVersion; dr["server"] = association.Server; dr["handle"] = association.Handle; dr["assoc_type"] = association.AssociationType; dr["session_type"] = association.SessionType; dr["secret"] = association.Secret; dr["expiration"] = association.Expiration; Associations.Rows.Add(dr); Associations.AcceptChanges(); }
/// <summary> /// Translates a DataRow matching the correct schema /// into an Association object. /// </summary> /// <param name="dr">DataRow containing source data.</param> /// <returns>Populated Association object.</returns> private static Association ToAssociation(DataRow dr) { Association ar = new Association(); ar.ProtocolVersion = (ProtocolVersion)dr["protocol"]; ar.Server = (string)dr["server"]; ar.Handle = (string)dr["handle"]; ar.AssociationType = (string)dr["assoc_type"]; ar.SessionType = (string)dr["session_type"]; ar.Secret = (byte[])dr["secret"]; ar.Expiration = (DateTime)dr["expiration"]; return ar; }
/// <summary> /// Add an assocation to the database. /// </summary> /// <param name="association">Association to add.</param> public void Add(Association association) { string protoversion = ""; switch (association.ProtocolVersion) { case ProtocolVersion.V1Dot1: protoversion = "V1_1"; break; case ProtocolVersion.V2Dot0: protoversion = "V2_0"; break; } string sql = "INSERT INTO " + _tableName + " (Handle, Server, AssociationType, " + "SessionType, ProtocolVersion, Secret, Expiration) " + "VALUES ('" + FixSqlIn(association.Handle) + "', " + "'" + association.Server + "', " + "'" + association.AssociationType + "', " + "'" + association.SessionType + "', " + "'" + protoversion + "', " + "'" + Convert.ToBase64String(association.Secret) + "', " + "'" + association.Expiration.ToString("s", CultureInfo.InvariantCulture) + "') "; _conn.Open(); IDbCommand comm = _conn.CreateCommand(); comm.CommandText = sql; comm.ExecuteNonQuery(); _conn.Close(); }
/// <summary> /// Transforms the current record in a DataReader object into an Association object. /// </summary> /// <param name="dr">The DataReader object use.</param> /// <returns>A populated Association object.</returns> protected static Association ToAssociation(IDataRecord dr) { Association ar = new Association(); switch ((string)dr["ProtocolVersion"]) { case "V2_0": ar.ProtocolVersion = ProtocolVersion.V2Dot0; break; case "V1_1": ar.ProtocolVersion = ProtocolVersion.V1Dot1; break; } ar.Server = (string)dr["Server"]; ar.Handle = FixSqlOut((string)dr["Handle"]); ar.AssociationType = (string)dr["AssociationType"]; ar.SessionType = (string)dr["SessionType"]; ar.Secret = Convert.FromBase64String((string)dr["Secret"]); ar.Expiration = ((DateTime)dr["Expiration"]); return ar; }
/// <summary> /// Perform an association request with an OpenID Provider. /// </summary> /// <param name="server">URL to the OpenID Provider.</param> /// <param name="associationManager">The IAssociationPersistence object to use for persistence.</param> /// <param name="version">The ProtocolVersion to use.</param> /// <param name="encryption">The key encryption type to use.</param> /// <returns>Populated Association object, or null.</returns> internal static Association CreateAssociation(Uri server, IAssociationPersistence associationManager, ProtocolVersion version, KeyEncryption encryption) { if (server == null) { throw new ArgumentNullException("server"); } if (associationManager == null) { throw new ArgumentNullException("associationManager"); } NameValueCollection sd = new NameValueCollection(); DiffieHellmanManaged dhm = new DiffieHellmanManaged(); sd["openid.mode"] = "associate"; switch (version) { case ProtocolVersion.V2Dot0: sd["openid.ns"] = ProtocolUri.OpenId2Dot0.AbsoluteUri; break; case ProtocolVersion.V1Dot1: if (encryption == KeyEncryption.DHSHA256) { encryption = KeyEncryption.DHSHA1; } break; } byte[] pubkey = null; DHParameters dp; switch (encryption) { case KeyEncryption.None: sd["openid.assoc_type"] = "HMAC-SHA1"; switch (version) { case ProtocolVersion.V2Dot0: sd["openid.session_type"] = "no-encryption"; break; case ProtocolVersion.V1Dot1: sd["openid.session_type"] = ""; break; } break; case KeyEncryption.DHSHA1: pubkey = dhm.CreateKeyExchange(); dp = dhm.ExportParameters(true); sd["openid.assoc_type"] = "HMAC-SHA1"; sd["openid.session_type"] = "DH-SHA1"; sd["openid.dh_modulus"] = Utility.UnsignedToBase64(dp.P); sd["openid.dh_gen"] = Utility.UnsignedToBase64(dp.G); sd["openid.dh_consumer_public"] = Utility.UnsignedToBase64(pubkey); break; case KeyEncryption.DHSHA256: pubkey = dhm.CreateKeyExchange(); dp = dhm.ExportParameters(true); sd["openid.assoc_type"] = "HMAC-SHA256"; sd["openid.session_type"] = "DH-SHA256"; sd["openid.dh_modulus"] = Utility.UnsignedToBase64(dp.P); sd["openid.dh_gen"] = Utility.UnsignedToBase64(dp.G); sd["openid.dh_consumer_public"] = Utility.UnsignedToBase64(pubkey); break; } Tracer.Write("Opening connection to OpenID Provider."); string response = ""; string actualLocation = null; response = Utility.MakeRequest(server, "POST", sd, out actualLocation); NameValueCollection association = null; Association retassoc = null; if (response != null) { Tracer.Write("Association response received."); association = Utility.SplitResponse(response); } else { Tracer.Write("No association response received."); switch (encryption) { case KeyEncryption.DHSHA256: Tracer.Write("Falling back to DHSHA1"); encryption = KeyEncryption.DHSHA1; retassoc = CreateAssociation(server, associationManager, version, encryption); if (retassoc != null) { return retassoc; } break; case KeyEncryption.DHSHA1: Tracer.Write("Falling back to No-encryption"); encryption = KeyEncryption.None; retassoc = CreateAssociation(server, associationManager, version, encryption); if (retassoc != null) { return retassoc; } break; } return null; } if (association["error"] != null) { Tracer.Write("Association response contains error. - " + association["error"]); return null; } if (encryption == KeyEncryption.DHSHA1 || encryption == KeyEncryption.DHSHA256) { Tracer.Write("Expecting DHSHA1 or DHSHA256."); StringBuilder vals = new StringBuilder(); foreach (string key in association.Keys) { vals.AppendLine(key + ": " + association[key]); } if (association["enc_mac_key"] == null) { Tracer.Write("No encoded MAC key returned! Received " + vals.ToString()); } if (association["enc_mac_key"] != null) { Tracer.Write("Encrypted association key is present."); byte[] serverpublickey = Convert.FromBase64String(association["dh_server_public"]); byte[] mackey = Convert.FromBase64String(association["enc_mac_key"]); byte[] dhShared = dhm.DecryptKeyExchange(serverpublickey); byte[] shaShared = new byte[0]; if (encryption == KeyEncryption.DHSHA1) { Tracer.Write("Decoding DHSHA1 Association."); SHA1 sha1 = new SHA1CryptoServiceProvider(); shaShared = sha1.ComputeHash(Utility.EnsurePositive(dhShared)); } else if (encryption == KeyEncryption.DHSHA256) { Tracer.Write("Decoding DHSHA256 Association."); SHA256 sha256 = new SHA256Managed(); shaShared = sha256.ComputeHash(Utility.EnsurePositive(dhShared)); } byte[] secret = new byte[mackey.Length]; for (int i = 0; i < mackey.Length; i++) { secret[i] = (byte)(mackey[i] ^ shaShared[i]); } association["mac_key"] = Convert.ToBase64String(secret); } else { Tracer.Write("Error: Received plaintext association when expecting encrypted."); return null; } } Tracer.Write("Building association"); retassoc = new Association(); retassoc.AssociationType = association["assoc_type"]; retassoc.Expiration = DateTime.UtcNow.AddSeconds(Convert.ToDouble(association["expires_in"], CultureInfo.InvariantCulture)); retassoc.Handle = association["assoc_handle"]; retassoc.ProtocolVersion = version; retassoc.Server = server.AbsoluteUri; retassoc.SessionType = association["session_type"]; retassoc.Secret = Convert.FromBase64String(association["mac_key"]); return retassoc; }