I’m trying to create a custom authentication plugin for WMS 2009 in C#.
I managed to implement something that for some reason blocks all requests…
[ComVisible(true)]
[Guid("C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE")]
public class AuthenticationPlugin : IWMSBasicPlugin, IWMSAuthenticationPlugin, IWMSAuthenticationContext
private const string SubKey = "SOFTWARE\\Microsoft\\Windows Media\\Server\\RegisteredPlugins\\Authentication\\{C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE}";
[ComRegisterFunction]
public static void RegisterFunction(Type t)
{
try
{
RegistryKey regHKLM = Registry.LocalMachine;
regHKLM = regHKLM.CreateSubKey(SubKey);
regHKLM.SetValue(null, "UC WMS Authentication plugin");
RegistryKey regHKCR = Registry.ClassesRoot;
regHKCR = regHKCR.CreateSubKey("CLSID\\{C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE}\\Properties");
regHKCR.SetValue("Name", CustomC WMS Authentication plugin");
regHKCR.SetValue("Author", "Me");
regHKCR.SetValue("CopyRight", "Copyright 2009. All rights reserved");
regHKCR.SetValue("Description", "Enables custom WMS authentication");
}
catch (Exception error)
{
Console.WriteLine(error.Message, "Inside RegisterFunction(). Cannot Register.");
}
}
[ComUnregisterFunction]
public static void UnRegisterFunction(Type t)
{
try
{
RegistryKey regHKLM = Registry.LocalMachine;
regHKLM.DeleteSubKey(SubKey);
RegistryKey regHKCR = Registry.ClassesRoot;
regHKCR.DeleteSubKeyTree("CLSID\\{C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE}");
regHKCR.DeleteSubKeyTree("CSEventTest.CSEventPlugin");
}
catch (Exception error)
{
Console.WriteLine(error.Message, "Cannot delete a subkey.");
}
}
#region IWMSBasicPlugin Members
public void InitializePlugin(IWMSContext serverContext, WMSNamedValues namedValues, IWMSClassObject classFactory)
{
}
public void ShutdownPlugin()
{
}
public void EnablePlugin(ref int flags, ref int heartbeatPeriod)
{
}
public void DisablePlugin()
{
}
public object GetCustomAdminInterface()
{
return null;
}
public void OnHeartbeat()
{
}
#endregion
#region IWMSAuthenticationPlugin Members
public IWMSAuthenticationContext CreateAuthenticationContext()
{
return (IWMSAuthenticationContext)this;
}
public int GetFlags()
{
return Convert.ToInt32(WMS_AUTHENTICATION_FLAGS.WMS_AUTHENTICATION_ANONYMOUS, CultureInfo.InvariantCulture);
}
public string GetPackageName()
{
return "Custom WMS Authentication";
}
public string GetProtocolName()
{
return "Basic";
}
#endregion
#region IWMSAuthenticationContext Members
public void Authenticate(object responseBlob, IWMSContext userContext, IWMSContext presentationContext, IWMSCommandContext commandContext, IWMSAuthenticationCallback callBack, object context)
{
callBack.OnAuthenticateComplete(WMS_AUTHENTICATION_RESULT.WMS_AUTHENTICATION_SUCCESS, null, context);
}
public IWMSAuthenticationPlugin GetAuthenticationPlugin()
{
return (IWMSAuthenticationPlugin)this;
}
public string GetImpersonationAccountName()
{
return String.Empty;
}
public int GetImpersonationToken()
{
return 0;
}
public string GetLogicalUserID()
{
return this.GetImpersonationAccountName();
}
#endregion
}
Can anyone spot why this is happening?
Also, is there any way I could have a look at the code for the standard Anonymous Authentication plugin already installed on the server? Is it in an assembly somewhere?
Thanks.
I ran into the same issue. It isn’t enough to return success status from the Authenticate method.
Your implemented method must retrieve a handle to a valid Windows Login. Search the net for C# examples of how to call this method: http://msdn.microsoft.com/en-us/library/aa378184%28VS.85%29.aspx
Store the IntPtr you get back from the LogonUser call and implement the GetImpersonationToken method like so:
Somehow the plug-in is able to tie that integer value back to a real windows account. I created a local account on the server that was in the Power Users group and used its username and password in the LogonUser method with the server being the domain. Once it is able to do so, the media should stream.
My whole IWMSAuthenticationPlugin is as follows (it uses basic authentication):