Friday, January 18, 2008

.NET Open Source

Microsoft published some of the .NET assemblies:


* Mscorlib.DLL
* System.DLL
* System.Data.DLL
* System.Drawing.DLL
* System.Web.DLL
* System.Web.Extensions.DLL
* System.Windows.Forms.DLL
* System.XML.DLL
* WPF (UIAutomation*.dll, System.Windows.DLL, System.Printing.DLL, System.Speech.DLL, WindowsBase.DLL, WindowsFormsIntegration.DLL, Presentation*.dll, some others)
* Microsoft.VisualBasic.DLL

The CardSpace related part don't seem to be in this list.

There are some part of the CardSpace documentation where source code would really help to build interoperable parties.
On the other hand: than I would have to think about the reference license. Which I don't want to do.

Original post where I found this information (german).

Thursday, January 17, 2008

ID Selector Selector

Is the Kevin Miller's Firefox extension an identity selector selector? I think that it is and was from the beginning (November 2006). When it was first released it was an identity selector selector that allowed one identity selector (CardSpace). Then Chuck Mortimore in December 2006 packaged his Firefox identity selector so that it was usable with the identity selector selector. Now the selector selector had something to select.

If you want to use e.g. DigitalMe with the identity selector selector than all you need to do is wrap it into a XPCOM component that follows Kevin's API.

Here is the current javascript interface:


Xmldapidentityselector.prototype = {

GetBrowserToken: function (
issuer , recipientURL, requiredClaims, optionalClaims ,
tokenType, privacyPolicy, privacyPolicyVersion,
serverCert, issuerPolicy ) {
}
}

All parameter are simple types except serverCert which is a nsIX509Cert. This could be a string too should somebody insist...

Calling the XPCOM component looks something like this:

var obj = null;
try {
var cidClass = Components.classes[cid];
if (cidClass != undefined) {
obj = cidClass.createInstance();
obj = obj.QueryInterface(Components.interfaces.IIdentitySelector);
} else {
IdentitySelector.reportError("onCallIdentitySelector", "the class " + cid + " is not installed");
return;
}
}
catch (e) {
IdentitySelector.throwError( "onCallIdentitySelector:", e);
}

/* Make the call to the selector */
identObject.targetElem.token = obj.GetBrowserToken(
data.issuer ,
data.recipient,
data.requiredClaims,
data.optionalClaims,
data.tokenType,
data.privacyUrl,
data.privacyVersion,
sslCert,
data.issuerPolicy );


Here is the current interface definition:

interface IIdentitySelector : nsISupports
{
void About();
string GetBrowserToken(in wstring issuerUri, in wstring recipientUrl,
in wstring requiredClaims, in wstring optionalClaims,
in wstring tokenType, in wstring privacyPolicy,
in long privacyPolicyVersion ,
in nsIX509Cert certificate, in wstring issuerPolicy );
string GetVersion();

readonly attribute wstring errorstring;
readonly attribute long errornumber;

};


This identity selector selector is not outside a browser; but... who cares!

Microsoft Group Surveilance Patent

Microsoft is patenting/patented (June 27, 2006) a group/employee/user "monitoring" system. The Times has a recent article about this. I read it here (german) first.

The word privacy does not occur in the application...

Dottie's Information Card


Congratulations, Mara and Chuck!

Wednesday, January 16, 2008

Novell's javascript mania

Today I was looking for a mailing list that announces new versions of the DigitalMe identity selector. I started looking at the Bandit's project home page. And surfed to "bandit-announcements" which sounded interesting too. From there the browser gets redirected to Novell's login page where I choose "create account". This looks like this when you have scripts disabled:



And like this when javascript is allowed for novell.com:



CSS anyone? And than: this is another example of a page that has a "XHTML strict" doctype but that is NOT "XHTML strict" (120 errors). Sad.

Another, more important thing, comes to mind: Why can't I use a self-issued information card to provide account information and why can't I login with that same card afterwards? Please...

BTW: I did not create an account.

Monday, January 14, 2008

Microsoft Passport lives

I thought that Microsoft Passport has failed and is dead or at least renamed, BUT today I found that it still lives.

Friday, January 11, 2008

RSA 2008 early bird


See you at the RSA 2008 interop!
Alan M. Turing



RSA® Conference 2008 Registration Receipt
This message is brought to you by RSA Conference. You are receiving this message because you are a registered attendee for RSA Conference 2008.

Thank you for registering for RSA Conference 2008, the world's leading information security Conference and Expo. The conference will be held April 7-11, at the Moscone Center in San Francisco, CA. The registration package you have selected and the benefits you will receive are outlined below in the Purchased Items section of the invoice. Please keep this email for future reference as it contains details about your RSA Conference 2008 registration.

Purchased Items
Name Type Quantity Price
Full Conference

Includes admittance to the "How to Network" session on Monday, admittance to all keynotes, track sessions and Peer-to-Peer sessions on Tuesday-Friday, admittance to the Forum, all activities in the exposition, admittance to the Welcome Reception on Monday night, admittance to the Codebreakers Bash on Thursday night, access to the Conference wireless network, scheduled Shuttle Transportation between the Conference Hotels and the Moscone Center, and Conference Materials (including an electronic copy of the proceedings and a Conference Bag) Paid 1 $x,xxx.xx
Concordia Project Seminar

Concordia Project: Interoperable Answers to Real-World Identity Deployments
The Concordia Project is a global initiative to drive interoperability across identity systems in use today. We'll review the Concordia Project ans showcase some actual multi-systems interoperability - demontrating the ability to achieve interoperability against specific 'high need' marketplace scenarios that deployers have articulated on the Concordia wiki. If you are a deployer who needs to understand how various indentity specs and standards owrk together today - or you need assurance that they are - this workshop is for you!
By registering for this seminar, you are automatically opting in to sharing your First Name, Last Name, Job Title, Company Name and Email Address with Concordia. If you do not want Concordia to have these details, you will have the opportunity to opt out on the next page.
Paid 1 $0.00
Liberty Alliance Seminar

Liberty Alliance: identity Federation and Web Services: Happening Today - Enabling Tomorrow
Learn about the Liberty Alliance protocols, and see how CA, HP, Intel, NTT Corporation, Ping Identity and RSA, The Security Division of EMC, are successfully utilizing these proven standards to implement state-of-the-art identity management solutions that strengthen security, increase privacy and offer end users and deploying organizations new levels of simplicity.
By registering for this seminar, you are automatically opting in to sharing your First Name, Last Name, Job Title, Company Name and Email Address with Liberty Alliance. If you don ot want Liberty Alliance to have these details, you will have the opportunity to opt out on the next page.
Paid 1 $0.00
Total $x,xxx.xx

The Moscone Center
747 Howard Street
San Francisco, CA 94103

xmldap code used in opensso

Gerry Beuchelt blogged about a deep-dive event the opensso team is having on the Microsoft campus. He sent an email to Chuck that some of the code used in opensso is from the openinfocard project. That's cool. Additionally they found a wrong namespace used in X509 authentication. A part of the code that is currently not used in the xmldap IdP. I corrected this and added a JUNIT test for this authentication method. Hopefully we will be able to accept X509 and other authentication methods in the xmldap IdP soon too.
Actually a year ago Chuck and I were thinking of integrating our code into opensso and continue to work there on the code. I wrote a LoginModule for Sun's Access Manager and sent it to Chuck to forward it to the opensso team which Chuck knows from his time at Sun.

Thursday, January 10, 2008

id selector advertising reloaded

My current favorite value for the id selector advertising HTTP header "X-ID-Selector":

version='urn:osis:infocard:2008-04'; name='urn:osis:infocard:names:openinfocard'; capabilities='+nossl+javascript-issuerpolicy'

  • version has a constant value until we change the spec for this HTTP header
  • name is one from a OSIS defined list
  • capabilities is a string of capabilities.
    • "+" indicated support for a capability.
    • "-" indicates missing support for a capability

These three capabilities are the first (and currently only) ones I think that matter to a relying party.
What needs to be defined is a list of capabilities that define the relationship between the RP and the id selector, and are relevant to the RP in regard of what response is generated to the HTTP request.

update: Mike Jones suggested to use the string ISIPv1 to denote capabilities of the id selector in regard to the features listed in the interop plan that can be downloaded from the User-Centric Identity Interop Google Group's page. I see this string "ISIPv1" as a placeholder for the "real" capabilities that need to be defined. So maybe ISIPv1 means "+nossl+issuerpolicy+javascript". As long as the list of relevant capabilites (for the relationship to the RP) is this short I don't see much sense in having the ISIPv1 string. The discussion arose from the fact that sending an additional HTTP header means more bytes to be send for each request the browser sends. I agree to this point. So "ISIPv1-issuerpolicy" makes sense. I would like the value of the header to be somewhat human readable. So maybe the following is a shorter alternative that we can live with:
v=1; name='openinfocard'; idv='0.9.9'; c='ISIPv1-issuerpolicy'
jshelper denoting a javascript helper object which interface needs to be defined. idv beeing the version of the id selector.
Someone suggested a "morehere" part of the HTTP header... The value of this would be the URL of the capabilties metadata e.g.: morehere='https://xmldap.org/capabilities?name=%n&idv=%idv' or morehere='http://axel.nennker.de/c?name=%n&idv=%idv'. I must say: I don't like this but if somebody conjures an example of the returned metadata and this is much longer or complicate than the capabilities part of the header value proposed here, than I might see sense in this capabilities by reference approach.

This image shows (a local install of ) the XMLDAP relying party displaying the value of the X-ID-Selector HTTP header:

Sunday, January 06, 2008

axman icardie.dll

Today I gave http://www.metasploit.com/users/hdm/tools/axman/ a try on icardie.dll. axman is a somewhat dated (August 2006) but apparently still useful tool.
Well, at first I let axman run its normal fuzzing tests against my fully patched Windows XP system and guess: Boom. IE7 crashed. To be more precise: some component/ActiveX/... inside IE7 crashed and took IE7 down with it.
some more digging reveiled that dao360.dll is old. Updating the jet4 engine with SP8 fails though because the service pack claims that a newer version is already installed...

After this promising start I let axman work on the classid {19916E01-B44E-4e31-94A4-4696DF46157B} which is, you guessed it: "InformationCardSigninHelper Class".


var ax_name = '{19916E01-B44E-4e31-94A4-4696DF46157B}';
ax[ax_name] = new Array();
ax[ax_name]['Info'] = 'InformationCardSigninHelper Class';
ax[ax_name]['Server'] = 'C:\\WINDOWS\\system32\\icardie.dll';
ax[ax_name]['SafeScript'] = new Array(3, 1);
ax[ax_name]['FunctionCount'] = 22;
ax[ax_name]['Functions'] = new Array();
ax[ax_name]['Functions'][0] = new Array();
ax[ax_name]['Functions'][1] = new Array();
ax[ax_name]['Functions'][2] = new Array();
ax[ax_name]['Functions'][3] = new Array();
ax[ax_name]['Functions'][4] = new Array();
ax[ax_name]['Functions'][5] = new Array();
ax[ax_name]['Functions'][6] = new Array();
ax[ax_name]['Functions'][7] = new Array();
ax[ax_name]['Functions'][7]['Name'] = 'isInstalled';
ax[ax_name]['Functions'][7]['Return'] = 'VARIANT_BOOL';
ax[ax_name]['Functions'][7]['ArgCount'] = 0;
ax[ax_name]['Functions'][7]['Args'] = new Array();
ax[ax_name]['Functions'][7]['Type'] = 'PropGet';
ax[ax_name]['Functions'][8] = new Array();
ax[ax_name]['Functions'][8]['Name'] = 'PrivacyUrl';
ax[ax_name]['Functions'][8]['Return'] = 'BSTR';
ax[ax_name]['Functions'][8]['ArgCount'] = 0;
ax[ax_name]['Functions'][8]['Args'] = new Array();
ax[ax_name]['Functions'][8]['Type'] = 'PropGet';
ax[ax_name]['Functions'][9] = new Array();
ax[ax_name]['Functions'][9]['Name'] = 'PrivacyUrl';
ax[ax_name]['Functions'][9]['Return'] = 'void';
ax[ax_name]['Functions'][9]['ArgCount'] = 1;
ax[ax_name]['Functions'][9]['Args'] = new Array();
ax[ax_name]['Functions'][9]['Args'][0] = 'BSTR';
ax[ax_name]['Functions'][9]['Type'] = 'PropPut';
ax[ax_name]['Functions'][10] = new Array();
ax[ax_name]['Functions'][10]['Name'] = 'PrivacyVersion';
ax[ax_name]['Functions'][10]['Return'] = 'VARIANT';
ax[ax_name]['Functions'][10]['ArgCount'] = 0;
ax[ax_name]['Functions'][10]['Args'] = new Array();
ax[ax_name]['Functions'][10]['Type'] = 'PropGet';
ax[ax_name]['Functions'][11] = new Array();
ax[ax_name]['Functions'][11]['Name'] = 'PrivacyVersion';
ax[ax_name]['Functions'][11]['Return'] = 'void';
ax[ax_name]['Functions'][11]['ArgCount'] = 1;
ax[ax_name]['Functions'][11]['Args'] = new Array();
ax[ax_name]['Functions'][11]['Args'][0] = 'VARIANT*';
ax[ax_name]['Functions'][11]['Type'] = 'PropPut';
ax[ax_name]['Functions'][12] = new Array();
ax[ax_name]['Functions'][12]['Name'] = 'Issuer';
ax[ax_name]['Functions'][12]['Return'] = 'BSTR';
ax[ax_name]['Functions'][12]['ArgCount'] = 0;
ax[ax_name]['Functions'][12]['Args'] = new Array();
ax[ax_name]['Functions'][12]['Type'] = 'PropGet';
ax[ax_name]['Functions'][13] = new Array();
ax[ax_name]['Functions'][13]['Name'] = 'Issuer';
ax[ax_name]['Functions'][13]['Return'] = 'void';
ax[ax_name]['Functions'][13]['ArgCount'] = 1;
ax[ax_name]['Functions'][13]['Args'] = new Array();
ax[ax_name]['Functions'][13]['Args'][0] = 'BSTR';
ax[ax_name]['Functions'][13]['Type'] = 'PropPut';
ax[ax_name]['Functions'][14] = new Array();
ax[ax_name]['Functions'][14]['Name'] = 'issuerPolicy';
ax[ax_name]['Functions'][14]['Return'] = 'BSTR';
ax[ax_name]['Functions'][14]['ArgCount'] = 0;
ax[ax_name]['Functions'][14]['Args'] = new Array();
ax[ax_name]['Functions'][14]['Type'] = 'PropGet';
ax[ax_name]['Functions'][15] = new Array();
ax[ax_name]['Functions'][15]['Name'] = 'issuerPolicy';
ax[ax_name]['Functions'][15]['Return'] = 'void';
ax[ax_name]['Functions'][15]['ArgCount'] = 1;
ax[ax_name]['Functions'][15]['Args'] = new Array();
ax[ax_name]['Functions'][15]['Args'][0] = 'BSTR';
ax[ax_name]['Functions'][15]['Type'] = 'PropPut';
ax[ax_name]['Functions'][16] = new Array();
ax[ax_name]['Functions'][16]['Name'] = 'value';
ax[ax_name]['Functions'][16]['Return'] = 'BSTR';
ax[ax_name]['Functions'][16]['ArgCount'] = 0;
ax[ax_name]['Functions'][16]['Args'] = new Array();
ax[ax_name]['Functions'][16]['Type'] = 'PropGet';
ax[ax_name]['Functions'][17] = new Array();
ax[ax_name]['Functions'][17]['Name'] = 'value';
ax[ax_name]['Functions'][17]['Return'] = 'void';
ax[ax_name]['Functions'][17]['ArgCount'] = 1;
ax[ax_name]['Functions'][17]['Args'] = new Array();
ax[ax_name]['Functions'][17]['Args'][0] = 'BSTR';
ax[ax_name]['Functions'][17]['Type'] = 'PropPut';
ax[ax_name]['Functions'][18] = new Array();
ax[ax_name]['Functions'][18]['Name'] = 'TokenType';
ax[ax_name]['Functions'][18]['Return'] = 'BSTR';
ax[ax_name]['Functions'][18]['ArgCount'] = 0;
ax[ax_name]['Functions'][18]['Args'] = new Array();
ax[ax_name]['Functions'][18]['Type'] = 'PropGet';
ax[ax_name]['Functions'][19] = new Array();
ax[ax_name]['Functions'][19]['Name'] = 'TokenType';
ax[ax_name]['Functions'][19]['Return'] = 'void';
ax[ax_name]['Functions'][19]['ArgCount'] = 1;
ax[ax_name]['Functions'][19]['Args'] = new Array();
ax[ax_name]['Functions'][19]['Args'][0] = 'BSTR';
ax[ax_name]['Functions'][19]['Type'] = 'PropPut';
ax[ax_name]['Functions'][20] = new Array();
ax[ax_name]['Functions'][20]['Name'] = 'RequiredClaims';
ax[ax_name]['Functions'][20]['Return'] = 'IUnknown*';
ax[ax_name]['Functions'][20]['ArgCount'] = 0;
ax[ax_name]['Functions'][20]['Args'] = new Array();
ax[ax_name]['Functions'][20]['Type'] = 'PropGet';
ax[ax_name]['Functions'][21] = new Array();
ax[ax_name]['Functions'][21]['Name'] = 'OptionalClaims';
ax[ax_name]['Functions'][21]['Return'] = 'IUnknown*';
ax[ax_name]['Functions'][21]['ArgCount'] = 0;
ax[ax_name]['Functions'][21]['Args'] = new Array();
ax[ax_name]['Functions'][21]['Type'] = 'PropGet';

I am happy that this test finished without crashing.

Friday, January 04, 2008

Ambigous Standards

One big thing that is missing in the openinfocard id selector is the export of self-issued cards in a CardSpace compatible way. It would be easy to export cards and to reimport them in another instance of the same selector (openinfocard). This was nevertheless never implemented because the real goal is to be able to export a card from the openinfocard selector and to import it into CardSpace and be recognized at a relyingparty.
Why is this hard?
Please read "A Technical Reference for the Information Card Profile V1.0" section "7.6.2. Regeneration of Input Parameters" and imagine yourself implementing this without getting too depressed before you even start.

During the holidays I started to implement this. Luckily there is a C++ implementation by Andrew Hodgkinson of the Bandit-Project.

But yesterday I noticed a difference between Andrew's code and the definition of an AES key that is defined in the information card's technical reference guide.

Encrypt the padded value using the AES-128 (Electronic Code Book mode) algorithm and the constant C (shown here) used as the encryption key.

C = f561e58b-3ebc-4e0c-940d-0a6ddc219dfd

Parts of the bytes are reversed while other parts are not...
Mark Oluper from Microsoft found a better definition of the constant that is compatible to Andrew's C++ byte array. You find it in the Identity Selector Interop Profile (page 45).

Encrypt the padded value with the AES-128 (Electronic Code Book mode) algorithm using the 16-byte constant below as the encryption key:
Encryption Key
{ 0x8b, 0xe5, 0x61, 0xf5, 0xbc, 0x3e, 0x0c, 0x4e, 0x94, 0x0d, 0x0a, 0x6d, 0xdc, 0x21, 0x9d, 0xfd }

I hope that Microsoft removes the ambigous definition. This stuff is hard enough without confusing "standards". The best thing Microsoft could do is to publish their code
  • to compute the OrgIdString/QualifiedOrgIdString from a pem encoded certificate
  • to compute the rpIdentifier from a certificate
  • to compute the keypair from the masterkey
  • of the RegenFunction
  • ...

have fun. Axel