Development of 'CheckAccess' methods

Mar 13, 2009 at 2:11 PM

I get your  excellent program – NetSqlAzMan,

It is perfect match of  administrative task and usability,  but I extended metods IAzManStorage for using using windows login

(executing methods by schedule in separate service … and only login saved in parameters)

    /// <summary>

            /// Checks the access [FOR Windows Users only].

            /// </summary>

            /// <param name="StoreName">Name of the store.</param>

            /// <param name="ApplicationName">Name of the application.</param>

            /// <param name="ItemName">Name of the itemName.</param>

            /// <param name="login">The windows login.</param>

            /// <param name="ValidFor">The valid for.</param>

            /// <param name="OperationsOnly">if set to <c>true</c> [operations only].</param>

            /// <param name="attributes">The attributes readed.</param>

            /// <param name="contextParameters">The context parameters.</param>

            /// <returns>AuthorizationType</returns>

            public AuthorizationType CheckAccess(string StoreName, string ApplicationName, string ItemName, string login, DateTime ValidFor, bool OperationsOnly, out List<KeyValuePair<string, string>> attributes, params KeyValuePair<string, object>[] contextParameters)

            {

                  return this.internalCheckAccess(StoreName, ApplicationName, ItemName, login, ValidFor, OperationsOnly, true, out attributes, contextParameters);

            }

 

            private AuthorizationType internalCheckAccess(string StoreName, string ApplicationName, string ItemName, string login, DateTime ValidFor, bool OperationsOnly, bool retrieveAttributes, out List<KeyValuePair<string, string>> attributes, params KeyValuePair<string, object>[] contextParameters)

            {

                  List<byte> token = new List<byte>();

                  PrincipalContext principalContext = null;

                  try

                  {

                        principalContext = new PrincipalContext(ContextType.Domain);

                  }

                  catch { }

                  if (principalContext != null) //it is not good - better using both context simultaneously -  for get completely all user groups!

                  {

                        try

                        {

                              principalContext = new PrincipalContext(ContextType.Machine);

                        }

                        catch { }

                  }

                  UserPrincipal up = UserPrincipal.FindByIdentity(principalContext, login);

                  token.AddRange(SqlAzManItem.getSqlBinarySid(up.Sid));

                  PrincipalSearchResult<Principal> groups = up.GetGroups();

                  int groupsCount = 0;

                  foreach (Principal group in groups)

                  {

                        token.AddRange(SqlAzManItem.getSqlBinarySid(group.Sid));

                        groupsCount++;

                  }

 

                 

                  SqlConnection conn = new SqlConnection(this.db.Connection.ConnectionString);

                  conn.Open();

                  DataSet checkAccessResults = new DataSet();

                  System.Data.SqlClient.SqlCommand cmd = new SqlCommand("DirectCheckAccess", conn);

                  cmd.CommandType = CommandType.StoredProcedure;

                  cmd.Parameters.AddWithValue("@STORENAME", StoreName);

                  cmd.Parameters.AddWithValue("@APPLICATIONNAME", ApplicationName);

                  cmd.Parameters.AddWithValue("@ITEMNAME", ItemName);

                  cmd.Parameters.AddWithValue("@OPERATIONSONLY", OperationsOnly);

                  cmd.Parameters.AddWithValue("@TOKEN", token.ToArray());

                  cmd.Parameters.AddWithValue("@USERGROUPSCOUNT", (object)groupsCount);

                  cmd.Parameters.AddWithValue("@VALIDFOR", ValidFor);

                  cmd.Parameters.AddWithValue("@LDAPPATH", DirectoryServicesUtils.rootDsePath);

                  cmd.Parameters.AddWithValue("@RETRIEVEATTRIBUTES", retrieveAttributes);

                  System.Data.SqlClient.SqlParameter pAuthorizationType = new System.Data.SqlClient.SqlParameter("@AUTHORIZATION_TYPE", (object)0);

                  pAuthorizationType.Direction = System.Data.ParameterDirection.InputOutput;

                  cmd.Parameters.Add(pAuthorizationType);

                  //BizRule Check CallBack

                  SqlDataAdapter checkAccessPartialResultsDataAdapter = new SqlDataAdapter(cmd);

                  try

                  {

                        checkAccessPartialResultsDataAdapter.Fill(checkAccessResults);

                  }

                  finally

                  {

                        conn.Close();

                  }

                  DataTable checkAccessPartialResultsDataTable = checkAccessResults.Tables[0];

                  DataTable checkAccessAttributesDataTable = (retrieveAttributes ? checkAccessResults.Tables[1] : new DataTable());

                  AuthorizationType result;

                  if (checkAccessPartialResultsDataTable.Select("BizRuleId IS NOT NULL").Length == 0)

                  {

                        //No business rules to check ... just return check access authorizationType

                        result = (AuthorizationType)((int)pAuthorizationType.Value);

                  }

                  else

                  {

                        //Transform DataRows into a Hierarchical Tree of Node(s)

                        IAzManApplication application = this[StoreName][ApplicationName];

                        ItemNode itemNode = this.buildTreeOfNodes(application, checkAccessPartialResultsDataTable, ItemName);

                        //Execute Biz Rules and Cut Nodes that returns false

                        Hashtable ctxParameters = new Hashtable();

                        foreach (KeyValuePair<string, object> kv in contextParameters)

                        {

                              ctxParameters.Add(kv.Key, kv.Value);

                        }

                        itemNode = this.executeBizRules(itemNode, new SqlAzManSID(up.Sid), ctxParameters);

                        //Compute final CheckAccess authorizationType

                        result = this.computeCheckAccessResult(itemNode, ref checkAccessAttributesDataTable);

                        if (result == AuthorizationType.Deny || result == AuthorizationType.Neutral)

                        {

                              checkAccessAttributesDataTable = new DataTable(); //no attributes

                        }

                  }

                  //Populate Attributes authorizationType

                  if (retrieveAttributes)

                  {

                        attributes = new List<KeyValuePair<string, string>>(checkAccessAttributesDataTable.Rows.Count);

                        foreach (DataRow dr in checkAccessAttributesDataTable.Rows)

                        {

                              KeyValuePair<string, string> kvp = new KeyValuePair<string, string>((string)dr[0], (string)dr[1]);

                              if (!attributes.Contains(kvp))

                              {

                                    attributes.Add(kvp);

                              }

                        }

                  }

                  else

                  {

                        attributes = new List<KeyValuePair<string, string>>();

                  }

                  return result;

            }

 

 

Could you include the interface expansion into you project?  (of course with refactoring the specific code in concordance with the program architecture)

  

 

With best wishes, Mineev Eugueni

 

 


Scopri tutte le novitа. Scarica Messenger 2009!

Mar 13, 2009 at 11:46 PM

Hi Mineev,

Are you aware of the “Kerberos Protocol Transition” ?
To impersonate a user, while not violating the rules of safety, but only to take its token is sufficient to do this:

WindowsIdentity otherIdentity = new WindowsIdentity ( "otheruser@domain.ext");


Kerberos Protocol Transition work on all machines with Windows Server 2003 or later.

In this way there would be no need to write this overload.

Please try and let me know.
Regards,
Andrea.