Tuesday, July 12, 2005

Maybe I'm being thick. Or perhaps its the speed I'm having to code at. But I think I've found a bug in Reporting Services.

Basically we have implemented custom security so that our logins to the Report Server are using details in a custom database. They are not Windows usernames/passwords. However when we use the web service api (ListSubscriptions) to return user's subscriptions we get nothing? After digging further with my best friend Reflector I found the following code in M$'s assemblies:

public ArrayList ListSubscriptions(string user, string report)
{
      ArrayList list1 = new ArrayList();
      string text1 = "select
             S.[SubscriptionID],
             S.[Report_OID],
             S.[Locale],
             S.[InactiveFlags],
             S.[DeliveryExtension],
             S.[ExtensionSettings],
             SUSER_SNAME(Modified.[Sid]), 
             Modified.[UserName],
             S.[ModifiedDate],
             S.[Description],
             S.[LastStatus],
             S.[EventType],
             S.[MatchData],
             S.[Parameters],
             S.[DataSettings],
             A.[TotalNotifications],
             A.[TotalSuccesses],
             A.[TotalFailures],
             SUSER_SNAME(Owner.[Sid]),
             Owner.[UserName],
             CAT.[Path],
             S.[LastRunTime],
             CAT.[Type],
             SD.NtSecDescPrimary
            from
             [Subscriptions] S inner join [Catalog] CAT on S.[Report_OID] = CAT.[ItemID]
             inner join [Users] Owner on S.OwnerID = Owner.UserID
             inner join [Users] Modified on S.ModifiedByID = Modified.UserID
             left outer join [SecData] SD on CAT.[PolicyID] = SD.[PolicyID] AND SD.AuthType = @AuthType
             left outer join [ActiveSubscriptions] A with (NOLOCK) on S.[SubscriptionID] = A.[SubscriptionID]";

      InstrumentedSqlCommand command1 = Storage.NewSqlCommand(text1, CommandType.Text, base.Connection, base.Transaction, base.SqlCommandTimeout);
      command1.Parameters.Add("@AuthType", WebConfigUtil.AuthenticationType);
      if ((user != null) && (user != ""))
      {
            this.AddClause(ref text1, ref flag1, "Owner.[Sid] = @UserSid");
            command1.Parameters.Add("@UserSid", Native.NameToSid(user));
      }

  <removed code>
}

Now the interesting bit is:

            this.AddClause(ref text1, ref flag1, "Owner.[Sid] = @UserSid");
            command1.Parameters.Add("@UserSid", Native.NameToSid(user));

Why are they trying to lookup a SID for my custom username? Of course this fails, which results in a WHERE clause that fails to grabs our subscriptions.

Has anyone else found this? Am I completely wrong?

BTW: I'm using Reporting Services SP 2.