9

I'm trying to programmatically determine whether the current user has certain permissions on a given Active Directory object (specifically in this case, I'm trying to determine whether the user has the "Send As" permission for another Exchange user or distribution list object).

I already figured out how to access the ntSecurityDescriptor attribute using ADSI: I can enumerate the ACEs in the IADsSecurityDescriptor's DiscretionaryACL property. But:

  • How do I determine from that data whether the "Send As"-permission is explicitly allowed or denied for a trustee?
  • How do I discover this when the permission has been granted indirectly via group membership? Do I really have to parse the effective permissions myself by (recursively) checking all groups the user is a member of? Surely there must be an API for that task...

FWIW, I'm coding in Delphi (i.e. native Win32 code) using the ActiveDs.dll typelibrary, so .NET-specific solutions won't really help me much unless their source code gives me clues to how to do the same thing in native code. The same goes for PowerShell.


Before anyone starts: I already know about the PR_EMS_AB_PUBLIC_DELEGATES and PR_EMS_AB_PUBLIC_DELEGATES_BL_O Extended MAPI properties. However, this is not what I'm after. These properties refer to the "Send on behalf of"-right (a.k.a. delegates), not the "Send As" permission, which is quite a different thing.

Oliver Giesen
  • 9,129
  • 6
  • 46
  • 82
  • @RRUZ : Thanks for stepping in but I'd rather keep the delphi-tag out of this, especially as some of the people able to answer this might even have it in their ignore list. I expect the eventual solution to be equally applicable to any programming language that can consume COM. – Oliver Giesen Nov 30 '11 at 23:19
  • Delphi-specific follow-up question here: http://stackoverflow.com/q/8524507/9784 – Oliver Giesen Dec 16 '11 at 01:00

1 Answers1

2

Here's the MSDN article that explains - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675580(v=VS.85).aspx. There is an attached sample that shows how to call the API.

Brian Desmond
  • 4,473
  • 1
  • 13
  • 11
  • Thanks, that looks very promising! Unfortunately, I won't have time to try this out until the week after next. I'll get back with the results (and hopefully an upvote and an accept) as soon as I know more. – Oliver Giesen Dec 03 '11 at 14:19
  • OK, I've now gotten a tiny bit further (it took a while for me to convert the example code to Delphi). I managed to create an example that compiles and runs but, being completely new to Windows security, I can't really say I understand what I'm doing or even what exactly it is I'm checking with this procedure... :( – Oliver Giesen Dec 14 '11 at 14:33
  • I'm sure I won't get around getting to to know the underlying concepts in the mid- to long term but I was hoping for a slightly more high-level approach to get me started. Ideally, I want to pass in an object SID and an access mask (though I still need to figure out, what I should be checking for in my particular case, i.e. the Exchange-specific "Send As"-right - I'm sure there must be a header file with constants for this, isn't there?) and get back `True` or `False` (I don't need to verify access for any user other than the current one). – Oliver Giesen Dec 14 '11 at 14:54
  • While looking into this example and how to translate it to Delphi I've also stumbled across the AuthZ-API. Would that also provide the functionality I need and if so, would there be any benefit in doing so? I was also wondering why the example was using `AccessCheckByObjectTypeResultList` rather than just `AccessCheck` or any of its other variations. The MSDN-summaries for these are almost identical... :-/ – Oliver Giesen Dec 14 '11 at 14:59
  • I think I've gotten quite a bit further in my understanding but I still can't get it to work. Apparently my Delphi translation of the example is still incorrect in some way: When I call `AccessCheckByObjectTypeResultList` it always fails and Last Error is 87 ("The parameter is incorrect") - yet I have no idea which of the bazillion parameters that this function accepts it is complaining about here... :( – Oliver Giesen Dec 22 '11 at 13:36