WSESimpleTCP UsernameToken Code.

I promised to post the code incorporating the SendHashed and UsernameToken logic in other blog, so here it is 🙂  MSN does not allow zip files yet, so I need to post as text.  This does the UsernameToken authentication as I have been talking about and also sets the GenericPrinciple in the UTM so you can use std declaritive security on your Web methods.  It is nice to put this up on a URL, as I am sure I will refer to it again and maybe it will help you with your project. 

// ServiceClient.cs
using System;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Addressing;
using Microsoft.Web.Services2.Messaging;
using Microsoft.Web.Services2.Security.Tokens;
using Microsoft.Web.Services2.Security;
using System.Xml;

namespace WSESimpleTCP
{
 /// <summary>
 /// This class derives from SoapClient and is a specific implementation
 /// of a client of the "Service" WSE service.
 ///
 /// Note: You could also use wsewsdl2 tool to generate a .cs proxy class.  Note
 /// the use the "-name" parm to do this correctly for tcp services.
 /// C:\Program Files\Microsoft WSE\v2.0\Tools\Wsdl>wsewsdl2 soap.tcp://wjs.mvptools.com/MyServ
 /// ice -name soap://service.contoso.com/MyServiceV1 output.cs
 /// </summary>
 public class ServiceClient : SoapClient
 {
  public ServiceClient( EndpointReference endpoint ) : base( endpoint ){}

  [SoapMethod("Ping")]
  public string Ping(string msg)
  {
   // No UsernameTaken sent.
   return (string)base.SendRequestResponse("Ping", msg).GetBodyObject(typeof(string));
  }

  [SoapMethod("GetDateString")]
  public string GetDateString()
  {
   // Add a UsernameToken to the envelope as the Service method requires it.
   string v = UserDB.CreateV("staceyw", "password");
   UsernameToken tok = new UsernameToken("staceyw", v, PasswordOption.SendHashed);

   SoapEnvelope env = new SoapEnvelope();
   env.Context.Security.Tokens.Add(tok);
   //env.Context.Security.Elements.Add(new MessageSignature(tok)); // will not call CustomAuthenticator at server.
   return (string)base.SendRequestResponse("GetDateString", env).GetBodyObject(typeof(string));
  }

  // Info only. Not used.
  // Example of how PasswordOption.SendHashed computes the Digest.
//  private static byte[] ComputePasswordDigest(byte[] nonce, DateTime created, string secret)
//  {
//   if ((nonce == null) || (nonce.Length == 0))
//    throw new ArgumentNullException("nonce");
//   if (secret == null)
//    throw new ArgumentNullException("secret");
//
//   byte[] b1 = Encoding.UTF8.GetBytes(XmlConvert.ToString(created.ToUniversalTime(), "yyyy-MM-ddTHH:mm:ssZ"));
//   byte[] b2 = Encoding.UTF8.GetBytes(secret);
//   byte[] b3 = new byte[nonce.Length + b1.Length + b2.Length];
//   Array.Copy(nonce, b3, nonce.Length);
//   Array.Copy(b1, 0, b3, nonce.Length, b1.Length);
//   Array.Copy(b2, 0, b3, (int) (nonce.Length + b1.Length), b2.Length);
//   return SHA1.Create().ComputeHash(b3);
//  }
  }
}

// Service.cs
using System;
using System.Collections;
using System.Globalization;
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Addressing;
using Microsoft.Web.Services2.Messaging;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
using System.Security.Permissions;
using System.Threading;

namespace WSESimpleTCP
{
 //
 // This class inheritits from SoapService and represents
 // a specific implementation of a Web service.
 //
 //[SoapActor("soap://service.contoso.com/MyServiceV1")]
 public class Service : SoapService
 {
  private static UserDB db;
  private const string host = "localhost"; //"wjs.mvptools.com"; // Note: does not work with "." at end.
  private const string viaString = "soap.tcp://" + host + "/MyService";
  private const string addrString = "soap://service.contoso.com/MyServiceV1";
  private static bool started = false;

  static Service()
  {
   db = new UserDB();
   User user1 = db.AddUser("staceyw", "password");
   user1.AddRole("WSEUsers");
  }

  internal static UserDB UserDB
  {
   get { return db; }
  }

  /// <summary>
  /// Return the string that was sent.
  /// </summary>
  /// <param name="msg"></param>
  /// <returns></returns>
  [SoapMethod("Ping")]
  public string Ping(string msg)
  {
   // If the user did not send a UsernameToken, we don’t check for one.
   // If they sent one, if will have to pass our UTM as that is called
   // for all methods in our service if UT supplied.
   return msg;
  }

  /// <summary>
  /// Return the current DateTime string on the server in UTC format.
  /// </summary>
  /// <returns></returns>
  [PrincipalPermissionAttribute(SecurityAction.Demand, Role = @"WSEUsers")]
  [SoapMethod("GetDateString")]
  public string GetDateString()
  {
   //Console.WriteLine("UPrinc:"+Thread.CurrentPrincipal.Identity.Name);
   //UsernameToken tok = this.GetUsernameToken();
   //Console.WriteLine("UserName:" + tok.Principal.Identity.Name);
   //Console.WriteLine("Is in WSEUsers:" + IsInRole("WSEUsers")); //@"MVPTools\NewGroup"));
   //
   //AssertUserRole("WSEUsers"); // Require login via UT, but any role.
   //Return Zulu time See: http://weblogs.asp.net/bclteam/archive/2004/05/21/136918.aspx
   return DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture);
  }

  /// <summary>
  /// Start the WSE service (i.e. Listen) if not already started.
  /// </summary>
  public static void Start()
  {         
   // Add the System.Type of the service (Service) to the SoapReceivers collection.
   // This will start a TCP-based listener if there isn’t one already started.
   //
   // Because we need to use Uri’s the Uri’s need to be in a valid Uri format
   // so we can’t just use something like "MyServiceV1" for address.
   // Also the address Uri must match the Classes SoapActor attribute if supplied
   // on the class.
   if ( started )
    return;
   EndpointReference endpoint = new EndpointReference(new Uri(addrString), new Uri(viaString));
   SoapReceivers.Add( endpoint, typeof(Service) );
   started = true;
   Console.WriteLine( "Listening at transport: " + endpoint.TransportAddress.ToString());
   Console.WriteLine( "Listening for messages at: " + endpoint.Address.Value );
  }

  /// <summary>
  /// Stop the WSE service.
  /// </summary>
  public static void Stop()
  {
   if ( ! started )
    return;
   EndpointReference endpoint = new EndpointReference(new Uri(addrString), new Uri(viaString));
   SoapReceivers.Remove(endpoint);
   started = false;
  }

  private bool IsInRole(string role)
  {
   if ( role == null )
    throw new ArgumentNullException("role");

   SoapContext requestContext = RequestSoapContext.Current;
   if ( requestContext == null )
    return false;

   // Get the UsernameToken that was used to sign the SOAP request.
   UsernameToken token = GetUsernameToken(requestContext);
   if ( token == null ) // (token == null || !token.Principal.IsInRole("Tellers"))
    return false;

   if ( token.Principal.IsInRole(role) )
    return true;
   return false;
  }

  /// <summary>
  /// Verify the current principal is in the role.  The
  /// token generic principal is set in the UTM.
  /// </summary>
  /// <param name="role"></param>
  private void AssertUserRole(string role)
  {
   SoapContext requestContext = RequestSoapContext.Current;
   if ( requestContext == null )
    throw new ApplicationException("Only SOAP requests are permitted.");

   // Get the UsernameToken that was used to sign the SOAP request.
   UsernameToken token = GetUsernameToken(requestContext);
   if ( token == null ) // (token == null || !token.Principal.IsInRole("Tellers"))
    throw new UnauthorizedAccessException();

   // If roles is null. We accept any roles.  UsernameToken must still
   // pass our UTM as we required a UsernameToken (i.e. must know username and pw).
   if ( role == null )
    return; // Ok to pass.

   if ( ! token.Principal.IsInRole(role) )
    throw new UnauthorizedAccessException();
  }

  /// <summary>
  /// Get the UsernameToken attached to the soap message.  If
  /// no token attached, return null.
  /// </summary>
  /// <param name="requestContext"></param>
  /// <returns></returns>
  private UsernameToken GetUsernameToken()
  {
   // Look through all the tokens in the Tokens collection
   // for a UsernameToken.
   SoapContext requestContext = RequestSoapContext.Current;
   if ( requestContext == null )
    throw new ApplicationException("Only SOAP requests are permitted.");
   return GetUsernameToken(requestContext);
  }

  private UsernameToken GetUsernameToken(SoapContext requestContext)
  {
   foreach (SecurityToken tok in requestContext.Security.Tokens)
   {
    if (tok is UsernameToken)
     return (UsernameToken)tok;
   }
   return null;
  }
  /// <summary>
  /// Returns the UsernameToken in the soap request if found; otherwise null.
  /// </summary>
  /// <param name="requestContext"></param>
  /// <returns></returns>
  private UsernameToken GetBodySigningToken(SoapContext requestContext)
  {
   UsernameToken token = null;
   foreach (ISecurityElement securityElement in requestContext.Security.Elements)
   {
    if (securityElement is MessageSignature)
    {
     MessageSignature sig = (MessageSignature)securityElement;
     if ((sig.SignatureOptions &
      SignatureOptions.IncludeSoapBody) != 0)
     {
      SecurityToken sigToken = sig.SigningToken;
      if (sigToken is UsernameToken)
       token = (UsernameToken)sigToken;
     }
    }
   }
   return token;
  }
 }
}

// CustomAuthenticator.cs
using System;
using System.Security.Permissions;
using Microsoft.Web.Services2.Security.Tokens;
using System.Text;
using System.Security.Principal;
using System.Threading;

namespace WSESimpleTCP
{
 [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
 public class CustomAuthenticator : UsernameTokenManager
 {
  /// <summary>
  /// Returns the password or password equivalent for user token
  /// using our internal database.
  /// </summary>
  /// <param name="token"></param>
  /// <returns>
  /// The verifier (V) stored in the DB.  This must exactly
  /// match the string that was passed to the UsernameToken constructor
  /// at the client; otherwise the authentication will fail.
  /// </returns>
  protected override string AuthenticateToken(UsernameToken token)
  {
   if (token == null)
    throw new ArgumentNullException();

   UserDB db = Service.UserDB;
   User user = db.FindUser(token.Username);
   if ( user == null )
    return null;
   string v = db.DecryptEV(user.EV);

   // Set the principal to a generic one.
   GenericIdentity gi = new GenericIdentity(user.UserName);
   GenericPrincipal gp = new GenericPrincipal(gi, user.Roles);
   token.Principal = gp;
   Thread.CurrentPrincipal = gp;
   return v;
  }
 }
}

// User.cs
using System;
using System.Collections;

namespace WSESimpleTCP
{
 /// <summary>
 /// Describes a user in our DB.
 /// </summary>
 public sealed class User
 {
  private string userName; // UserName.
  private string ev;   // Encrypted Verifier (EV).
  private readonly ArrayList roles = new ArrayList();

  private User()
  {
  }

  internal static User CreateUser(string userName, string ev)
  {
   if ( userName == null )
    throw new ArgumentNullException("userName");
   if ( ev == null )
    throw new ArgumentNullException("ev");

   User u = new User();
   u.userName = userName;
   u.ev = ev;
   return u;
  }

  public string UserName
  {
   get { return this.userName; }
  }

  /// <summary>
  /// Encrypted Verifier (EV).  Value is encrypted with Rijndael when
  /// stored in the DB.  The unencrypted value is "v" (or sha(password+salt) ).
  /// </summary>
  public string EV
  {
   get { return this.ev; }
  }

  public string[] Roles
  {
   get { return (string[])this.roles.ToArray(typeof(string)); }
  }

  /// <summary>
  /// Salt can be stored along side user in db record or dynamically
  /// generated.  We dynamically generate based off userName.
  /// </summary>
  public string Salt
  {
   get
   {
    return UserDB.GetSalt(userName);
   }
  }

  public bool IsInRole(string roleName)
  {
   foreach(string role in roles)
   {
    if ( String.Compare(role, roleName, true) == 0 )
     return true;
   }
   return false;
  }

  public void AddRole(string roleName)
  {
   if ( roleName == null )
    throw new ArgumentNullException("roleName");

   if ( IsInRole(roleName) )
    return;
   roles.Add(roleName);
  }

  public void RemoveRole(string roleName)
  {
   int index = -1;
   for(int i=0; i < roles.Count; i++)
   {
    string role = roles[i] as string;
    if ( String.Compare(role, roleName, true) == 0 )
    {
     index = i;
     break;
    }
   }
   if ( index >= 0 )
    roles.RemoveAt(index);
  }
 }
}

// UserDB.cs
using System;
using System.Text;
using System.Collections;
using System.Security.Cryptography;
using System.IO;

namespace WSESimpleTCP
{
 /// <summary>
 /// Simple DB to hold User object as an example.  This would
 /// normally go against a SQL table or file, etc.
 /// </summary>
 public sealed class UserDB
 {
  private static string sec = "asdfasfdasdfasdf"; // Secret_key to be stored safely.
  private readonly Hashtable db = new Hashtable( new CaseInsensitiveHashCodeProvider(), new CaseInsensitiveComparer() );
  private static readonly SHA1 sha1 = SHA1.Create();
  private static readonly HMACSHA1 hsha1 = (HMACSHA1)HMACSHA1.Create();
  private readonly RijndaelManaged rm;
  
  public UserDB()
  {
   // rm key defaults: key = 32, iv = 16.
   rm = new RijndaelManaged();
   PasswordDeriveBytes db = new PasswordDeriveBytes(sec, null);
   rm.Key = db.GetBytes(32);
   rm.IV = db.GetBytes(16);
  }

  public User FindUser(string userName)
  {
   return db[userName] as User;
  }

  public User AddUser(string userName, string password)
  {
   if ( userName == null )
    throw new ArgumentNullException("userName");

   if ( password == null )
    throw new ArgumentNullException("password");

   if ( FindUser(userName) != null )
    throw new InvalidOperationException("User already exists.");

   string v = CreateV(userName, password);
   string ev = CreateEV(v);
   User user = User.CreateUser(userName, ev);
   db[userName] = user;
   return user;
  }

  public string DecryptEV(string ev)
  {
   byte[] eBytes = Convert.FromBase64String(ev);
   byte[] clearV = Decrypt(eBytes);
   return Convert.ToBase64String(clearV);
  }

  private string CreateEV(string v)
  {
   byte[] evBytes = Encrypt(Convert.FromBase64String(v));
   return Convert.ToBase64String(evBytes);
  }

  internal static string CreateV(string userName, string password)
  {
   // v = sha1(password + salt)
   byte[] bytes = Encoding.UTF8.GetBytes(password + GetSalt(userName));
   byte[] hash = sha1.ComputeHash(bytes);
   string v = Convert.ToBase64String(hash);
   return v;
  }

  private static byte[] GetKey(string password)
  {
   return null;
  }

  internal static string GetSalt(string userName)
  {
   if ( userName == null )
    throw new ArgumentNullException("userName");

   userName = userName.ToLower();
   PasswordDeriveBytes pdb = new PasswordDeriveBytes(userName, null);
   pdb.IterationCount = 1000;
   pdb.HashName = "SHA1";

   byte[] saltBytes = pdb.GetBytes(10);
   return Convert.ToBase64String(saltBytes);
  }

  private byte[] Encrypt(byte[] data)
  {
   //Get an encryptor from rm instance.
   ICryptoTransform encryptor = rm.CreateEncryptor();
           
   //Encrypt the data.
   using(MemoryStream msEncrypt = new MemoryStream())
   using(CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
   {
    //Write all data to the crypto stream and flush it.
    csEncrypt.Write(data, 0, data.Length);
    csEncrypt.FlushFinalBlock();
    return msEncrypt.ToArray();
   }
  }

  private byte[] Decrypt(byte[] encrypted)
  {
   //Get an encryptor.
   ICryptoTransform decryptor = rm.CreateDecryptor();
           
   //Decrypt the data.
   using(MemoryStream msDecrypt = new MemoryStream(encrypted))
   using(CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
   {
    //Write all data to the crypto stream and flush it.
    byte[] fromEncrypt = new byte[encrypted.Length];
    int bytesRead = csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
  
    byte[] clearBytes = new byte[bytesRead];
    Buffer.BlockCopy(fromEncrypt, 0, clearBytes, 0, bytesRead);
    return clearBytes;
   }
  }
 }
}

// Form1.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Security.Cryptography;

using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Addressing;
using Microsoft.Web.Services2.Messaging;
using Microsoft.Web.Services2.Security.Tokens;

namespace WSESimpleTCP
{
 /// <summary>
 /// Summary description for Form1.
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  private const string host = "localhost"; //"wjs.mvptools.com";
  private ServiceClient client = null;

  private System.Windows.Forms.GroupBox groupBox1;
  private System.Windows.Forms.GroupBox groupBox2;
  private System.Windows.Forms.Button btnStart;
  private System.Windows.Forms.Button btnStop;
  private System.Windows.Forms.Button btnGetDate;
  private System.Windows.Forms.Button btnPing;
  private System.Windows.Forms.RichTextBox rtbOutput;
  private System.Windows.Forms.Button btnClear;
  private System.Windows.Forms.Button button1;
  /// <summary>
  /// Required designer variable.
  /// </summary>
  private System.ComponentModel.Container components = null;

  public Form1()
  {
   //
   // Required for Windows Form Designer support
   //
   InitializeComponent();

   //
   // TODO: Add any constructor code after InitializeComponent call
   //
  }

  public ServiceClient Client
  {
   get
   {
    if ( this.client == null )
    {
     // via is the network endpoint describing host, transport, and port.
     // address is the WSE endpoint.
     Uri via = new Uri("soap.tcp://" + host + "/MyService");
     Uri address = new Uri("soap://service.contoso.com/MyServiceV1");
     this.client = new ServiceClient(new EndpointReference(address, via));
    }
    return this.client;
   }
  }

  /// <summary>
  /// Clean up any resources being used.
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows Form Designer generated code
  /// <summary>
  /// Required method for Designer support – do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
   this.groupBox1 = new System.Windows.Forms.GroupBox();
   this.btnStop = new System.Windows.Forms.Button();
   this.btnStart = new System.Windows.Forms.Button();
   this.groupBox2 = new System.Windows.Forms.GroupBox();
   this.btnGetDate = new System.Windows.Forms.Button();
   this.btnPing = new System.Windows.Forms.Button();
   this.rtbOutput = new System.Windows.Forms.RichTextBox();
   this.btnClear = new System.Windows.Forms.Button();
   this.button1 = new System.Windows.Forms.Button();
   this.groupBox1.SuspendLayout();
   this.groupBox2.SuspendLayout();
   this.SuspendLayout();
   //
   // groupBox1
   //
   this.groupBox1.Controls.Add(this.btnStop);
   this.groupBox1.Controls.Add(this.btnStart);
   this.groupBox1.Location = new System.Drawing.Point(232, 16);
   this.groupBox1.Name = "groupBox1";
   this.groupBox1.Size = new System.Drawing.Size(200, 96);
   this.groupBox1.TabIndex = 0;
   this.groupBox1.TabStop = false;
   this.groupBox1.Text = "WSE Service";
   //
   // btnStop
   //
   this.btnStop.Location = new System.Drawing.Point(104, 32);
   this.btnStop.Name = "btnStop";
   this.btnStop.TabIndex = 1;
   this.btnStop.Text = "Stop";
   this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
   //
   // btnStart
   //
   this.btnStart.Location = new System.Drawing.Point(16, 32);
   this.btnStart.Name = "btnStart";
   this.btnStart.TabIndex = 0;
   this.btnStart.Text = "Start";
   this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
   //
   // groupBox2
   //
   this.groupBox2.Controls.Add(this.btnGetDate);
   this.groupBox2.Controls.Add(this.btnPing);
   this.groupBox2.Location = new System.Drawing.Point(8, 16);
   this.groupBox2.Name = "groupBox2";
   this.groupBox2.Size = new System.Drawing.Size(208, 96);
   this.groupBox2.TabIndex = 1;
   this.groupBox2.TabStop = false;
   this.groupBox2.Text = "WSE Client Proxy Methods:";
   //
   // btnGetDate
   //
   this.btnGetDate.Location = new System.Drawing.Point(112, 40);
   this.btnGetDate.Name = "btnGetDate";
   this.btnGetDate.TabIndex = 1;
   this.btnGetDate.Text = "GetDate";
   this.btnGetDate.Click += new System.EventHandler(this.btnGetDate_Click);
   //
   // btnPing
   //
   this.btnPing.Location = new System.Drawing.Point(24, 40);
   this.btnPing.Name = "btnPing";
   this.btnPing.TabIndex = 0;
   this.btnPing.Text = "Ping";
   this.btnPing.Click += new System.EventHandler(this.btnPing_Click);
   //
   // rtbOutput
   //
   this.rtbOutput.Location = new System.Drawing.Point(8, 144);
   this.rtbOutput.Name = "rtbOutput";
   this.rtbOutput.Size = new System.Drawing.Size(424, 120);
   this.rtbOutput.TabIndex = 2;
   this.rtbOutput.Text = "";
   //
   // btnClear
   //
   this.btnClear.Location = new System.Drawing.Point(352, 120);
   this.btnClear.Name = "btnClear";
   this.btnClear.TabIndex = 3;
   this.btnClear.Text = "Clear";
   this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
   //
   // button1
   //
   this.button1.Location = new System.Drawing.Point(208, 112);
   this.button1.Name = "button1";
   this.button1.TabIndex = 4;
   this.button1.Text = "button1";
   this.button1.Click += new System.EventHandler(this.button1_Click);
   //
   // Form1
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.ClientSize = new System.Drawing.Size(440, 277);
   this.Controls.Add(this.button1);
   this.Controls.Add(this.btnClear);
   this.Controls.Add(this.rtbOutput);
   this.Controls.Add(this.groupBox2);
   this.Controls.Add(this.groupBox1);
   this.Name = "Form1";
   this.Text = "WSE with UsernameToken security Sample";
   this.groupBox1.ResumeLayout(false);
   this.groupBox2.ResumeLayout(false);
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new Form1());
  }

  private void btnStart_Click(object sender, System.EventArgs e)
  {
   Service.Start();
   this.btnStart.Enabled = false;
   this.btnStop.Enabled = true;
   this.rtbOutput.AppendText("WSE Service started.\n");
  }

  private void btnPing_Click(object sender, System.EventArgs e)
  {
   string reply = Client.Ping("Hello");
   this.rtbOutput.AppendText("Reply:" + reply + "\n");
  }

  private void btnStop_Click(object sender, System.EventArgs e)
  {
   Service.Stop();
   this.btnStart.Enabled = true;
   this.btnStop.Enabled = false;
   this.rtbOutput.AppendText("WSE Service stopped.\n");
  }

  private void btnGetDate_Click(object sender, System.EventArgs e)
  {
   string reply = Client.GetDateString();
   this.rtbOutput.AppendText(reply+"\n");
  }

  private void btnClear_Click(object sender, System.EventArgs e)
  {
   this.rtbOutput.Clear();
  }

  private void button1_Click(object sender, System.EventArgs e)
  {
   // Max = 256 bits or 32 bytes.
   // IV = 16 bytes or 128 bits.
   RijndaelManaged rm = new RijndaelManaged();
   
   foreach(KeySizes ks in rm.LegalKeySizes)
   {
    Console.WriteLine("Max:"+ks.MaxSize);
    Console.WriteLine("Min:"+ks.MinSize);
   }
   Console.WriteLine("IV.len:"+rm.IV.Length);
   Console.WriteLine("Key.len:"+rm.Key.Length);
   Console.WriteLine("Key size:"+rm.KeySize);
  }
 }
}

//
// app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="microsoft.web.services2" type="Microsoft.Web.Services2.Configuration.WebServicesConfiguration, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <microsoft.web.services2>
    <diagnostics>
      <policyTrace enabled="false" />
      <trace enabled="false" />
    </diagnostics>
    <security>
      <securityTokenManager type="WSESimpleTCP.CustomAuthenticator, WSESimpleTCP" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" qname="wsse:UsernameToken" />
    </security>
  </microsoft.web.services2>
</configuration>

— William

See also:
Designing Role-Based Security Models for .NET
http://www.15seconds.com/issue/041208.htm

Michele’s Security Resource Page (code samples for this article can be found here)
http://www.dotnetdashboard.net/sessions/securitysummit.aspx

Michele’ Blog
http://www.dasblonde.net

Advertisements
This entry was posted in C#. Bookmark the permalink.

2 Responses to WSESimpleTCP UsernameToken Code.

  1. William says:

    It seems that if the threads are reused (and they are) Thread.CurrentPrinciple is not reset. So to be sure we don\’t reuse last user\’s principle object, we should null the CurrentPrinciple before we leave our web method(s). This kinda sucks as we need to do this for every method. O well.[PrincipalPermissionAttribute(SecurityAction.Demand, Role = @"WSEUsers")][SoapMethod("GetDateString")]public string GetDateString(){ try { // Method code. } finally { Thread.CurrentPrincipal = null; }}–William

Comments are closed.