Error on property NameIDPolicy.AllowCreate when parsing legitimate SAML Request coming from Shibboleth - itfoxtec-identity-saml2

I am implementing a SingleSignOn solution (IdP) based on your software and having a little problem when receiving a SAMLRequest (http redirect), generated by Shibboleth.
This request contains an element: <samlp:NameIDPolicy AllowCreate="1"/>
The SAML2 standard (https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf lines 2186 an later) states that this is a boolean attribute.
The SAML standard is only talking about the possible values "true" and "false"
But the xml standard https://www.w3.org/TR/xmlschema11-2/#boolean (on which SAML2 standard is based) specifies: booleanRep ::= 'true' | 'false' | '1' | '0'
So the element sent by Shibboleth should be correct.
But when parsing the SAML request I get a error message:
System.FormatException: String '1' was not recognized as a valid Boolean.
I examined the sources in github
In the ITfoxtec project this NamedIdPolicy is defined in https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/blob/662544c8e08c46bf1736bd72fcf31d06aeac1d9d/src/ITfoxtec.Identity.Saml2/Schemas/NameIDPolicy.cs
And the parsing is done in https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/blob/662544c8e08c46bf1736bd72fcf31d06aeac1d9d/src/ITfoxtec.Identity.Saml2/Util/GenericTypeConverter.cs
The error message was generated by line 121: return (T)Convert.ChangeType(value, typeof(T));
I recreated the error message with this code snippet in LinqPad:
bool? AllowCreate = GenericConvertValueToNullable<bool>("true");
AllowCreate.Dump(); // returns boolean value true
AllowCreate = GenericConvertValueToNullable<bool>("1"); // Triggers error in Convert.ChangeType call
AllowCreate.Dump();
T? GenericConvertValueToNullable<T>(string value) where T : struct
{
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
else
{
return (T)Convert.ChangeType(value, typeof(T));
}
}
The error occurs when converting the "1" value to boolean
I also found a possible solution
Insert these lines before the Convert.ChangeType line:
if(typeof(T) == typeof(bool))
{
int intValue;
if(int.TryParse(value, out intValue))
{
if (intValue == 0 || intValue == 1)
{
return (T)Convert.ChangeType(intValue, typeof(bool));
}
}
}
In the result code, 'true' | 'false' | '1' | '0' can all be used as valid values
I tested that "7", "-1", "x" still cause the error message, as they are not valid accoording to xml standard, so thats also correct.
Is it possible that you make these changes, and release a new version of the NuGet package?
Maybe there are more boolean attributes that need complying to the xml standard?

The link https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/blob/662544c8e08c46bf1736bd72fcf31d06aeac1d9d/src/ITfoxtec.Identity.Saml2/Schemas/NameIDPolicy.cs is to a working Draft.
The SAML 2.0 core standard from 2005:
https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf where NameIDPolicy.AllowCreate is described in chapter 3.4.1.1.
I don't think AllowCreate can be anything else then true and false according to the SAML 2.0 core standard.
1) UPDATE
It is possible to add support for not strictly SAML 2.0 Authn request and thereby accept NameIdPolicy.AllowCreate non SAML 2.0 standard values.
You can implement your own version of the Saml2AuthnRequest class inherited from Saml2Request class.
Where you change the NameIdPolicy to your own NameIdPolicy implementation.
public MyCustomNameIdPolicy NameIdPolicy { get; set; }
The MyCustomNameIdPolicy is implemented based on the NameIdPolicy code, where the AllowCreate property type is changed to a string.
public string AllowCreate { get; set; }
The AllowCreate will then accept both true, false, 1 and 0 as strings.
2) UPDATE
The reason for the problem you describe is probably because you need to implement MyCustomNameIdPolicy in GetXContent line 144 and Read line 169.

Related

Gatling .sign issue

I am trying to build a Get request as follows and I would like CaseReference value to be populated via feeder .feed(CaseProviderSeq) but for some reason it's not picking CaseReference value and printing following for my println statement in .sign statement bellow
PATH KJ: /caseworkers/554355/jurisdictions/EMPLOYMENT/case-types/Manchester_Multiples/cases/$%7BCaseReference%7D/event-triggers/updateBulkAction_v2/token
My feeder CSV got following rows currently
1574761472170530
1574622770056940
so I am expecting this amended URL would be like
/caseworkers/554355/jurisdictions/EMPLOYMENT/case-types/Manchester_Multiples/cases/1574761472170530/event-triggers/updateBulkAction_v2/token
any idea what wrong I am doing here ??
.get(session => SaveEventUrl.replace(":case_reference","${CaseReference}").replaceAll("events", "") + s"event-triggers/${EventId}/token")
.header("ServiceAuthorization", s2sToken)
.header("Authorization", userToken)
.header("Content-Type","application/json")
.sign(new SignatureCalculator {
override def sign(request: Request): Unit = {
val path = request.getUri.getPath
println("PATH KJ: " + path)
request.getHeaders.add("uri", path)
}
})
This is not related to .sign, but your session attribute CaseReference not being interpreted. If you look closely you can see the braces %-encoded in $%7BCaseReference%7D.
Interpretation of the Gatling Expression Language strings happens only when a String is present when an Expression[Something] is needed1.
This bug you wrote is shown exactly in the warning in the documentation above.
I believe you can simply remove session => in your .get, so you are passing in a String rather than a Session => String2. That string will be implicitly converted to Expression[String]. That way Gatling will put the session attribute into the URL.
This happens because of the Scala implicit conversion.
In fact it is Session => Validation[String], because, again, of implicit conversions.

Sql Component :Consume multiple rows and mark them all as processed using onConsume

I configured camel sql component to read data from from database table . I have "onConsume" parameter working when i read one row at a time , but doesn't work when i try to read multiple rows at a time using "maxMessagesPerPoll". Here is what i tried ...
Working : When i read one row at a time and update the row using onConsume .
My consumer endpoint uri looks like :
sql:select * from REPORT where IS_VIOLATED != 'N' and TYPE = 'Provisioning'?consumer.delay=1000&consumer.onConsume=update REPORT set IS_VIOLATED = 'N' where REPORT_ID =:#REPORT_ID
Not working : When I configured camel's sql component to read configurable rows(using "maxMessagesPerPoll") . It reads multiple rows at a time but onConsume doesn't seem to work . I tried to tell camel to use IN operator and setting header value(REPORT_ID) with a array of values for IN clause.
My consumer endpoint uri now looks like :
sql:select * from REPORT where IS_VIOLATED != 'N' and TYPE = 'Provisioning'?consumer.delay=1000&maxMessagesPerPoll=3&consumer.useIterator=false&consumer.onConsume=update REPORT set IS_VIOLATED = 'N' where REPORT_ID in(:#REPORT_ID)
I might be doing something wrong here. I did enough searching on this already and found related post1, post2 . But it doesn't put me on correct path.
I need to be able to mark all the consumed rows to IS_VIOLATED = 'N' .
Thanks for your help.
I noticed that you set consumer.useIterator=false, and the doc says:
If true each row returned when polling will be processed individually. If false the entire java.util.List of data is set as the IN body.
So I think that because of this option, the :#REPORT_ID is no more understood, since it would be from the entire list and no more from each row.
Maybe removing this option would already be enough.
I also didn't understand why you changed the where clause from where REPORT_ID =:#REPORT_ID to where REPORT_ID in(:#REPORT_ID).
By carefully looking at the apache sql component doc :
I tried implementing custom processing stratergy, using attribute "processingStrategy"`.
public class ReportProcessingStratergy implements SqlProcessingStrategy {
#Override
public int commit(DefaultSqlEndpoint defaultSqlEndpoint, Exchange exchange, Object o, JdbcTemplate jdbcTemplate, String s) throws Exception {
s = s.replace("?","5066834,5066835,5066832");
return jdbcTemplate.update(s);
}
#Override
public int commitBatchComplete(DefaultSqlEndpoint defaultSqlEndpoint, JdbcTemplate jdbcTemplate, String s) throws Exception {
return 0;
}
}
configure spring bean :
<bean class="go.ga.ns.reconc.sl.ReportProcessingStratergy" id="reportProcessingStratergy">
now my sql consumer endpoint uri looks like :
sql:select * from REPORT where IS_VIOLATED != 'N' and TYPE = 'Provisioning'?consumer.delay=1000&maxMessagesPerPoll=3&consumer.useIterator=false&&processingStrategy=#reportProcessingStratergy&consumer.onConsume=update REPORT set IS_VIOLATED = 'N' where REPORT_ID in(?)
note :processingStrategy=#reportProcessingStratergy(# has significance as explained here, it did not work with out it)

AD returns Objectsid as String and SecurityIdentifier is failing interprete this

Usually AD returns 'Objectsid' as a byte[]. So I type cast the value returned by AD in to byte[]. This procedure worked against several AD but not in one case. In this AD environment, I get following exception.
Exception: Unable to cast object of type 'System.String' to type 'System.Byte[]'. (System.InvalidCastException)
To debug this I started checking data-type of the value returned by AD, and it was system.string not byte[]. I printed this string and it was garbage. Then I passed this string to SecurityIdentifier() and I got exception again.
Exception: Value was invalid. Parameter name: sddlForm (System.ArgumentException)
Code:
//Using System.DirectoryServices.Protocols objects
object s = objSrEc[k1].Attributes[(string)obj3.Current][0];
string x = s.GetType().FullName;
if (x.ToLower() == "system.byte[]")
{
byte[] bSID = ((byte[])s);
if (bSID != null)
{
SecurityIdentifier SID = new SecurityIdentifier(bSID, 0);
String ObjectSID = SID.Value;
}
}
else if (x.ToLower() == "system.string")
{
SecurityIdentifier SID = new SecurityIdentifier((String)s); //ssdl excception
String ObjectSID = SID.Value;
}
This is the first time I am seeing AD return string data for ObjectSID. I have run my code against many AD servers. I am planning to check the data-type of ObjectSID in AD schema.
Do any one come across this behavior? Should I call the Win32 api ConvertByteToStringSid()?
Thanks
Ramesh
Sorry for reviving a graveyard post, but I had the same issue a year or so ago, managed to find out why and I figured I'd at least share the reason behind this behavior.
When using the System.DirectoryServices.Protocols namespace, all attribute values should be either a) a byte array, or b) a UTF-8 string. Thing is, the developers at Microsoft figured that they should help people by returning a string when the byte array returned from the underlying LDAP API can be formatted as one, and the byte array itself when the UTF-8 conversion fails. However, this is only true for the indexer of the DirectoryAttribute class, and not for the iterator (which always returns the byte array) or the GetValues method.
The safest way to always get a byte array when you want the SID is, as previously mentioned by others, the GetValues method.
I came through the same. Found this behavior normal when deal with ForeignSecurityPrincipals, however recently found this when translate attributes of built-in groups from some old Win 2K3 domains.
I don't like this as can't just ask the result attribute to tell me via GetType() what type are you and what should I do with you ( GetValues(Attribute.GetType()) ). One of the solutions was reading all attributes definition from AD schema, but this part might be a bit heavy (depends what you're looking for) although it was only a small part of overall AD processing the solution was performing.
Cheers,
Greg

How to get LDAP unboundid AttributeSyntax?

I'm trying to find out the unboundid AttributeSyntax type for a specific attribute name and it's simply not working.
Here's the example test code that I'm using to achieve this:
#Test
public void testLDAPSchema() {
try {
LDAPConnection connection = new LDAPConnection();
connection.connect("hessmain", 389);
connection.bind("CN=Administrator,CN=Users,DC=FISHBOWL,DC=NET", "password");
Schema s = connection.getSchema();
System.out.println(s.toString());
AttributeTypeDefinition atd = s.getAttributeType("directReports");
Set<AttributeTypeDefinition> oat = s.getOperationalAttributeTypes();
Set<AttributeSyntaxDefinition> l = s.getAttributeSyntaxes();
AttributeSyntaxDefinition asd1 = s.getAttributeSyntax(atd.getOID());
AttributeSyntaxDefinition asd2 = s.getAttributeSyntax(atd.getSyntaxOID());
AttributeSyntaxDefinition asd3 = s.getAttributeSyntax(atd.getBaseSyntaxOID());
connection.close();
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
From the above code, all the sets are empty. This also means that no matter which OID I pass to the schema getAttributeSyntax method that I will simply get a null return.
Is there any reason why I can't get the attribute syntaxes from an Active Directory server schema?
Thanks
I don't think that this is specific to the UnboundID LDAP SDK for Java. I'm not sure that Active Directory exposes this information over LDAP. When I perform a general LDAP search to retrieve schema information, I can see the attributeTypes and objectClasses attributes, but ldapSyntaxes isn't returned (and in fact ldapSyntaxes doesn't appear in the list of attribute types).
Similarly, none of the attribute type definitions includes a USAGE element, which is what is used to indicate that the attribute type is operational (e.g., "USAGE directoryOperation").
It may well be that Active Directory simply doesn't report this information at all. It could be that it provides some other non-standard way to get this information (e.g., a control or extended operation, or some other entry that can be retrieved), but if there is then I don't know about it.

WPF Validation Message in Xml

I have a WPF application which is displaying field validation messages by implementing the IDataErrorInfo interface. This is all working well.
What I want to do now is to break out the validation messages into an separate xml file so that validation message key value pairs can be stored outside of the code and can be easily maintained possibly by an end (super)user.
I was thinking of having a method something like:
private void ValidateRequiredField<T>(ref T field, string fieldName)
{
string error = null;
if (Equals(field, null)
|| (field is string
&& (string.IsNullOrEmpty(field.ToString())
|| field.ToString().Replace(" ", string.Empty).Length == 0)
)
|| (field is int
&& int.Parse(field.ToString()) == 0)
)
{
error = GetValueFromConfig(fieldName);
}
SetFieldDataError(fieldName, error);
}
Is the best way to store these key value pairs in an xml file? I seem to remember that there used to be a Microsoft Configuration Application Block but I can't see an equivalent in Enterprise Library 5.0. Is there a better way?
For anyone who may be pondering the same question...after much deliberating, I opted to use the Microsoft Enterprise Library 5.0

Resources