Moving micasa 1.5 trunk to Novell forge.
This commit is contained in:
471
ClientPasswordManager/c-sharp-net-credential/NetCredential.cs
Normal file
471
ClientPasswordManager/c-sharp-net-credential/NetCredential.cs
Normal file
@@ -0,0 +1,471 @@
|
||||
/***********************************************************************
|
||||
* File: NetCredential.cs
|
||||
* Author: Juan Carlos Luciani (jluciani@novell.com)
|
||||
*
|
||||
* Namespace: Novell.Security.ClientPasswordManager
|
||||
*
|
||||
* Classes implemented: NetCredential.
|
||||
*
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
*
|
||||
* This library 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 library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
***********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using Novell.Security;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Novell.Security.ClientPasswordManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of ICredentials that leverages the
|
||||
/// services of the SecretStore Client Service Wallet.
|
||||
/// </summary>
|
||||
public class NetCredential: ICredentials
|
||||
{
|
||||
#region Class Members and Defines
|
||||
|
||||
// This is temporary until we add code to interact with the SecretStore
|
||||
private class UserCache
|
||||
{
|
||||
public string m_userName;
|
||||
public CredentialCache m_credentialCache;
|
||||
|
||||
public UserCache()
|
||||
{
|
||||
m_userName = null;
|
||||
m_credentialCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
// This is temporary until we add code to interact with the SecretStore
|
||||
private static UserCache[] m_userCaches = new UserCache[10];
|
||||
|
||||
private string m_svcName = null;
|
||||
private string m_svcGroupName = null;
|
||||
private string m_userName = null;
|
||||
private string m_password = null;
|
||||
private string m_credScope = null;
|
||||
|
||||
private bool m_haveCredentials;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private static bool bMiCasaIsAvailable = false;
|
||||
private static Assembly assembly = null; //
|
||||
private static string MI_CASA_CLASS_NAME = "Novell.CASA.miCASA";
|
||||
|
||||
|
||||
static NetCredential()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
assembly = Assembly.LoadWithPartialName("Novell.CASA.miCASAWrapper");
|
||||
if (assembly != null)
|
||||
bMiCasaIsAvailable = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Dbg.trcError(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a NetCredential object for Windows Applications.
|
||||
///
|
||||
/// There is a high probability that services under the same group share the
|
||||
/// same user name and passwords. By specifying a service group name, the caller wants to
|
||||
/// take advantage of this to try to improve the user experience. If the service group
|
||||
/// name is not specified then no effort is made to share usernames and passwords with
|
||||
/// other services.
|
||||
///
|
||||
/// If the svcGroupNameIsRealmName parameter is set to true then it is assumed that
|
||||
/// the services in the group validate username and passwords against the same
|
||||
/// database or against synchronized databases.
|
||||
///
|
||||
/// If the svcGroupNameIsRealmName parameter is set to false then an attempt will be
|
||||
/// made to share passwords between the services in the group but services will be
|
||||
/// allowed to use different passwords. Specifying a service group does not mean
|
||||
/// that the system will not be able to obtain a username and password that is
|
||||
/// unique to a particular service.
|
||||
/// </summary>
|
||||
/// <param name="svcName">Name of service requesting credentials.</param>
|
||||
/// <param name="svcGroupName">Name of group to which the service belongs, can be null or zero length.</param>
|
||||
/// <param name="svcGroupNameIsRealmName">The group name is the name of the backend authentication realm.</param>
|
||||
/// <param name="userName">Name of the user.</param>
|
||||
/// <param name="password">User password if known, otherwise null or empty string.</param>
|
||||
public NetCredential(string svcName,
|
||||
string svcGroupName,
|
||||
bool svcGroupNameIsRealmName,
|
||||
string userName,
|
||||
string password)
|
||||
{
|
||||
// Check input parameters
|
||||
if (svcName == null
|
||||
|| svcName.Length == 0
|
||||
|| (svcGroupNameIsRealmName
|
||||
&& (svcGroupName == null
|
||||
|| svcGroupName.Length == 0))
|
||||
|| userName == null
|
||||
|| userName.Length == 0)
|
||||
{
|
||||
Dbg.trcError("NetCredential constructor- Invalid input parameter");
|
||||
throw new Exception("NetCredential constructor- Invalid input parameter");
|
||||
}
|
||||
|
||||
m_svcName = svcName;
|
||||
m_svcGroupName = svcGroupName;
|
||||
m_userName = userName;
|
||||
m_password = password;
|
||||
|
||||
// Determine the name under which the credentials are scoped
|
||||
if (svcGroupNameIsRealmName)
|
||||
m_credScope = m_svcGroupName;
|
||||
else
|
||||
m_credScope = m_svcName;
|
||||
|
||||
// Check if we need to update the credential cache
|
||||
if (password != null
|
||||
&& password.Length != 0)
|
||||
{
|
||||
if (bMiCasaIsAvailable)
|
||||
{
|
||||
UpdateMiCasaCredential(userName, password, m_svcName, svcGroupName);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateCredentialCache(userName, password, m_credScope);
|
||||
}
|
||||
|
||||
// Remember that there object has credentials associated with it to avoid
|
||||
// looking them up in the cache at a later time.
|
||||
m_haveCredentials = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indicate that we need to look up the credentials in the cache
|
||||
m_haveCredentials = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a NetCredential object.
|
||||
///
|
||||
/// No effort is made to share usernames and passwords with other services.
|
||||
/// </summary>
|
||||
/// <param name="svcName">Name of service requesting credentials.</param>
|
||||
/// <param name="userName">Name of the user.</param>
|
||||
/// <param name="password">User password if known, otherwise null or empty string. Not meaningfull if username is not specified.</param>
|
||||
public NetCredential(string svcName,
|
||||
string userName,
|
||||
string password)
|
||||
{
|
||||
// Check input parameters
|
||||
if (svcName == null
|
||||
|| svcName.Length == 0
|
||||
|| userName == null
|
||||
|| userName.Length == 0)
|
||||
{
|
||||
Dbg.trcError("NetCredential constructor- Invalid input parameter");
|
||||
throw new Exception("NetCredential constructor- Invalid input parameter");
|
||||
}
|
||||
|
||||
m_svcName = svcName;
|
||||
m_userName = userName;
|
||||
m_password = password;
|
||||
|
||||
// The credentials are scoped to the service name
|
||||
m_credScope = m_svcName;
|
||||
|
||||
// Check if we need to update the credential cache
|
||||
if (password != null
|
||||
&& password.Length != 0)
|
||||
{
|
||||
|
||||
if (bMiCasaIsAvailable)
|
||||
{
|
||||
UpdateMiCasaCredential(userName, password, m_svcName, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateCredentialCache(userName, password, m_credScope);
|
||||
}
|
||||
|
||||
// Remember that there object has credentials associated with it to avoid
|
||||
// looking them up in the cache at a later time.
|
||||
m_haveCredentials = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indicate that we need to look up the credentials in the cache
|
||||
m_haveCredentials = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a NetworkCredential instance from the cache.
|
||||
/// </summary>
|
||||
/// <param name="uriPrefix">A Uri that specifies the URI prefix of the resources that the credential is used for.</param>
|
||||
/// <param name="authType">The authentication scheme used by the host named in <i>uriPrefix</i>. </param>
|
||||
public void Remove(Uri uriPrefix,
|
||||
String authType)
|
||||
{
|
||||
// Only process requests for the "Basic" authentication scheme
|
||||
if (authType.ToUpper() == "BASIC")
|
||||
{
|
||||
|
||||
if (bMiCasaIsAvailable)
|
||||
{
|
||||
RemoveMiCasaCredential(uriPrefix.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we already have credentials
|
||||
if (m_haveCredentials)
|
||||
{
|
||||
// Clear the credentials.
|
||||
m_password = null;
|
||||
m_haveCredentials = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Lookup the credentials in the cache
|
||||
//
|
||||
// Synchronize access into the cache
|
||||
lock (m_userCaches)
|
||||
{
|
||||
// Look for the user's cache
|
||||
int i;
|
||||
for (i = 0; i < m_userCaches.Length; i++)
|
||||
{
|
||||
// Check if the user cache has been instantiated
|
||||
if (m_userCaches[i] != null)
|
||||
{
|
||||
if (m_userCaches[i].m_userName == m_userName)
|
||||
{
|
||||
// We found a cache for this user, remove the credentials.
|
||||
m_userCaches[i].m_credentialCache.Remove(new Uri("http://" + m_credScope, true), "Basic");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbg.trcError("NetCredential.GetCredential- Unsupported authentication scheme");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains the network credentials necessary to gain access to the resources associated
|
||||
/// with the specified uri prefix.
|
||||
/// </summary>
|
||||
/// <param name="uriPrefix">Uri that specifies the URI prefix of resources that the credential grant access to</param>
|
||||
/// <param name="authType">The authentication scheme used by the resource</param>
|
||||
/// <returns>NetworkCredential object or null if not successful</returns>
|
||||
public NetworkCredential GetCredential(Uri uriPrefix,
|
||||
String authType)
|
||||
{
|
||||
NetworkCredential cred = null;
|
||||
|
||||
// Only process requests for the "Basic" authentication scheme
|
||||
if (authType.ToUpper() == "BASIC")
|
||||
{
|
||||
|
||||
if (bMiCasaIsAvailable)
|
||||
{
|
||||
return GetMiCasaCredential(m_svcName, m_svcGroupName);
|
||||
}
|
||||
|
||||
// Check if we already have credentials
|
||||
if (m_haveCredentials)
|
||||
{
|
||||
// Create NetworkCredential object with the credentials that we have.
|
||||
cred = new NetworkCredential(m_userName, m_password);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Lookup the credentials in the cache
|
||||
//
|
||||
// Synchronize access into the cache
|
||||
lock (m_userCaches)
|
||||
{
|
||||
// Look for the user's cache
|
||||
int i;
|
||||
for (i = 0; i < m_userCaches.Length; i++)
|
||||
{
|
||||
// Check if the user cache has been instantiated
|
||||
if (m_userCaches[i] != null)
|
||||
{
|
||||
if (m_userCaches[i].m_userName == m_userName)
|
||||
{
|
||||
// We found a cache for this user, check if we already have the
|
||||
// necessary credentials.
|
||||
cred = m_userCaches[i].m_credentialCache.GetCredential(new Uri("http://" + m_credScope, true), "Basic");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbg.trcError("NetCredential.GetCredential- Unsuported authentication scheme");
|
||||
}
|
||||
|
||||
return cred;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the credential cache with the supplied credentials.
|
||||
/// </summary>
|
||||
/// <param name="userName">Name of the user.</param>
|
||||
/// <param name="password">User password.</param>
|
||||
/// <param name="credScope">Credential scope.</param>
|
||||
private void UpdateCredentialCache(string userName, string password, string credScope)
|
||||
{
|
||||
// Check if we already have a cache for the user
|
||||
lock (m_userCaches)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m_userCaches.Length; i++)
|
||||
{
|
||||
// Check if the user cache has been instantiated
|
||||
if (m_userCaches[i] != null)
|
||||
{
|
||||
if (m_userCaches[i].m_userName == userName)
|
||||
{
|
||||
// A user cache has already been instantiated, check if
|
||||
// we already have a cache entry.
|
||||
if (m_userCaches[i].m_credentialCache.GetCredential(new Uri("http://" + credScope, true), "Basic") != null)
|
||||
{
|
||||
// We have a cache entry, remove it.
|
||||
m_userCaches[i].m_credentialCache.Remove(new Uri("http://" + credScope, true), "Basic");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Instantiate user cache and use it
|
||||
m_userCaches[i] = new UserCache();
|
||||
|
||||
// Setup user cache
|
||||
m_userCaches[i].m_userName = userName;
|
||||
m_userCaches[i].m_credentialCache = new CredentialCache();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Exit if we failed to obtain a user cache
|
||||
if (i == m_userCaches.Length)
|
||||
return;
|
||||
|
||||
// Create NetworkCredential object and add it to the credential cache
|
||||
NetworkCredential cred = new NetworkCredential(userName, password);
|
||||
m_userCaches[i].m_credentialCache.Add(new Uri("http://" + credScope, true), "Basic", cred);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the following is micasa/secretstore code.
|
||||
private void UpdateMiCasaCredential(string sUsername, string sPassword, string sSecretID, string sSharedID)
|
||||
{
|
||||
|
||||
// call SetCredential through reflection
|
||||
Type type = assembly.GetType(MI_CASA_CLASS_NAME);
|
||||
object Instance = Activator.CreateInstance (type);
|
||||
|
||||
object[] arguments = new object[4];
|
||||
arguments[0] = sSecretID;
|
||||
arguments[1] = sSharedID;
|
||||
arguments[2] = sUsername;
|
||||
arguments[3] = sPassword;
|
||||
|
||||
object result;
|
||||
try
|
||||
{
|
||||
result = type.InvokeMember("SetBasicCredential", BindingFlags.InvokeMethod, null, Instance, arguments);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Dbg.trcError(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private NetworkCredential GetMiCasaCredential(string sSecretID, string sSharedID)
|
||||
{
|
||||
object oUsername;
|
||||
object oPassword;
|
||||
|
||||
Type type = assembly.GetType(MI_CASA_CLASS_NAME);
|
||||
object Instance = Activator.CreateInstance (type);
|
||||
|
||||
try
|
||||
{
|
||||
object[] arguments = new object[2];
|
||||
arguments[0] = sSecretID;
|
||||
arguments[1] = sSharedID;
|
||||
|
||||
// reflection call
|
||||
oUsername = type.InvokeMember("GetCredentialUsername", BindingFlags.InvokeMethod, null, Instance, arguments);
|
||||
oPassword = type.InvokeMember("GetCredentialPassword", BindingFlags.InvokeMethod, null, Instance, arguments);
|
||||
|
||||
if ((oUsername != null) & (oPassword != null))
|
||||
return new NetworkCredential(oUsername.ToString().Trim(), oPassword.ToString().Trim());
|
||||
|
||||
// invoke the GetUsername and GetPassword methods
|
||||
//object username = basicCred.InvokeMember("GetUsername", BindingFlags.InvokeMethod, null, result, null);
|
||||
//object password = basicCred.InvokeMember("GetPassword", BindingFlags.InvokeMethod, null, result, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Dbg.trcError(e.ToString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void RemoveMiCasaCredential(string sSecretID)
|
||||
{
|
||||
Type type = assembly.GetType(MI_CASA_CLASS_NAME);
|
||||
object Instance = Activator.CreateInstance (type);
|
||||
|
||||
try
|
||||
{
|
||||
object[] arguments = new object[2];
|
||||
arguments[0] = sSecretID;
|
||||
arguments[1] = null;
|
||||
|
||||
// reflection call
|
||||
type.InvokeMember("RemoveBasicCredential", BindingFlags.InvokeMethod, null, Instance, arguments);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Dbg.trcError(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user