Hi all, I have a function I wrote which grabs a list of security groups from a sql table and then combines that with the domain name to check the users security groups to decide what they have specific access too. The function works 100% perfect when I run it against a localhost database, the second I point it to a remote database with same data and same structure it dies returns all groups failed and I can't for the life of me figure out why.
Thanks in advance for any help anyone can give :)
<code>
// AD Groups the user belongs too
public Stack retGroups = new Stack();
#region Get security groups
private void getSecGroups() {
SqlConnection getGroups = new SqlConnection(connect);
// Select distinct from the database so you can create an array of unique security groups the user belongs too
SqlCommand sqlGroups = new SqlCommand(
"SELECT DISTINCT ADGroup FROM Security " +
"GROUP BY ADGroup ",getGroups);
try {
getGroups.Open();
SqlDataReader returned =
sqlGroups.ExecuteReader();
while(returned.Read()) {
Int32 i=0;
for(i=0; i < returned.FieldCount; i++) {
string adGroups = returned.GetValue(0).ToString();
// Check if user belongs to a security group against the database
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity);
bool retval = principal.IsInRole(@"" + domainName + "\\" + adGroups + "");
MessageBox.Show("Testing group: "+adGroups);
// it's being ignored again wtf
// add adGroup current entry to the array and loop back
if(retval == false) {
}
if(retval == true ) {
retGroups.Push("" + adGroups + "");
}
}
}
}
catch(Exception ex) {
MessageBox.Show("Error checking security groups: "+ex.Message);
}
finally {
getGroups.Close();
}
}
#endregion
</code>

principal.IsInRole working locally but not remotely?
SGI101
Thanks for the help
Tryin2Bgood
axg70
I'm getting confused as to what is changing and what is working. If you pass a literal string to IsInRole does it work when you are connecting to your local database How about when you connect to the remote database Do not change the literal used to test this. Use one of the roles found in the DB.
We have confirmed that IsInRole works in both cases, as it should. Now call whatever SQL code you use to get the roles from the local DB. Verify that you actually get data back (the data reader isn't null and has rows or the datatable has rows). If this works then change the connection string to the remote DB and run it again. If you don't get anything back then the conn string is incorrect.
If you are getting data back then now you need to eliminate the possibility that it is the data itself. Look at the data as it comes back from the DB locally. Does the syntax and the values match what you'll get back from the remote DB
Michael Taylor - 11/13/06
etcheverrjc
Client machine and account are the same in both cases
**EDIT**
Was playing with the code a bit more if I pass it as a literal string it works fine when connected to the remote datasource but when I seperate it and pass it with the escaped backslash it dies.
Azimuth
OK, so it wasn't an issue with the code or the database they were all doing exactly what they were supposed to. However I didn't know # sign was a special character in SQL2000 (guess it's not in SQL2005 which is what I had running on localhost). So, what I did was this, I escaped the character in SQL2000 using ## and then I had it replace the ## with # in code.
The # sign is a comment in SQL.
Thank you for the help michael! It is much appreciated.
So here's the final code if anyone has an issue like this again.
for(i=0; i < returned.FieldCount; i++) {
string adGroups = returned.GetValue(0).ToString();
string finGroups = adGroups.Replace("##", "#");
// Check if user belongs to a security group against the database
bool retval = principal.IsInRole(domainName + "\\" + finGroups);
// add adGroup current entry to the array and loop back
if(retval == false) {
MessageBox.Show(domainName+ @"\"+finGroups);
}
if(retval == true ) {
retGroups.Push("" + adGroups + "");
MessageBox.Show("Yay!");
}
}
jellofissi
I would wager that it is your domain name that is causing the problems. If I understand your problem correctly you are storing AD group names in a DB and want to compare them. In this case you should store the entire AD group name and not just the group name itself. Each AD group could potentially be in a different domain yet there could be a couple with the same name. For example:
\\Accounting\Administrators
\\Human Resources\Administrators
By storing the entire name you can just pass the group name to IsInRole. However I'm for maintainability so I'd recommend against storing the group name altogether. The problem with group names is that they can change. If a group name changes then your database would no longer work. Therefore I recommend storing the SID of the group instead as it'll be unique and can't change without deleting the actual group. The only problem you might have to contend with is built in local groups. In this case I believe they share a standard SID but if you're using AD this probably won't be much of an issue. Local, custom groups do not have this problem. You'll have to do some testing. Once you get the SID use SecurityIdentifier to create an object and pass it it to IsInRole.
As an aside you can increase the performance of your code by moving the code to get the principal of the current user outside the while loop. Technically speaking it is possible that the groups could change while the loop is running but this would be difficult to isolate and therefore really doesn't gain you anything.
Michael Taylor - 11/11/06
RaviKanthReddy
It sounds like bad data to me. Assuming that you are running the code from the same client machine ultimately the only thing that'll matter is the string that you pass to IsInRole. Did you verify that each row you get back from the DB (on the remote machine) is correct prior to calling IsInRole I'm wagering that something is wrong with the values you are getting back.
Now of course if the client machine is changing as well then any number of issues could be occurring. The first one that comes to mind is the security account under which you are running your client program may not have sufficient access to AD. If you are using a different client machine then try targeting the remote server from the client machine that does work. If you get the data you expect then it is your "new" client machine that is having the problem.
Michael Taylor - 11/13/06
esafari68
I'd wager that you are not getting back the data you think you are. Try dumping each row of data as it comes across the DB. It is likely that one or more rows contains data you aren't expecting. I'd wager a missing or extra slash somewhere. You can partially mitigate such as issue by changing from string concatenation (which I don't really trust) to a function that can handle this issue.
Michael Taylor - 11/13/06
Ying06
Right now I have it so everytime retval == false it returns a messagebox with the current sql entry and the domain name to check formatting and that it is pulling data properly.
Lastly, the local database and the remote database are identical in both content and structure.
I've updated the code a bit based on your recommendations (whats the command for blocking out a code segment don't see it in the WYSIWYG control bar for posting).
// get identityand groups for use in sql check
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity);
try {
getGroups.Open();
SqlDataReader returned =
sqlGroups.ExecuteReader();
while(returned.Read()) {
Int32 i=0;
for(i=0; i < returned.FieldCount; i++) {
string adGroups = returned.GetValue(0).ToString();
// Check if user belongs to a security group against the database
bool retval = principal.IsInRole(domainName + "\\" + adGroups); // we have security groups visually seperated by having a pound sign amended to them ie. #Group, could this be treated as an escape sequence Wasn't aware of # being viewed as one but it's the only thing I can think of at the moment
// add adGroup current entry to the array and loop back
if(retval == false) {
MessageBox.Show(domainName+ "\\" +adGroups);
}
if(retval == true ) {
retGroups.Push("" + adGroups + "");
MessageBox.Show("Yay!");
}
}
}
}
cookieCutter
Try this. Set domainName to whatever would be returned from the DB. Are you pulling it from the DB or setting it locally Set adGroups to whatever the DB would return. Then allow the call to see what happens, like so:
string domainName = ...; //whatever the DB would return
string adGroups = ...; //Whatever the DB would return (use a literal string, not the value from SQL
principal.IsInRole(domainName + "\\" + adGroups);
Is the message box value properly formatted when you look at it Is there a prefixed "\\" on the domain name or an extra slash in adGroups
Michael Taylor - 11/13/06