New sam system

Kai Krueger kai at
Wed Jul 31 13:22:02 GMT 2002

----- Original Message -----
From: "Jelmer Vernooij" <jelmer at>   Sent: Wednesday, July 31, 2002
5:53 PM

> [ Ok, I've switched off gpg signing for all samba lists... ]
> Hi!
> I'm working on the new sam system currently and was wondering whether
> the following patch should be applied to
> source/sam/SAM-Interface-handles.txt:
> -NTSTATUS sam_get_user_by_sid(NT_USER_TOKEN *access, uint32
access_desired, DOM_SID *usersid, SAM_USER_HANDLE **user)
> -NTSTATUS sam_get_user_by_name(NT_USER_TOKEN *access, uint32
access_desired, char *domain, char *name, SAM_USER_HANDLE **user)
> +NTSTATUS sam_get_user_by_sid(NT_USER_TOKEN *access, uint32
access_desired, DOM_SID *usersid, SAM_USER_HANDLE *user)
> +NTSTATUS sam_get_user_by_name(NT_USER_TOKEN *access, uint32
access_desired, char *domain, char *name, SAM_USER_HANDLE *user)

It depends upon what kind of structure the SAM_{USER, GROUP, DOMAIN}_HANDLE
actually implies, if this should be changed. The SAM-Interface-handles.txt
doesn't mention anything about what the handles actually are and as far as I
know this is mainly because it hasn't been decided upon.

Anyway, I'll try and explain the reason why these handles were introduced in
the first place and what they are supposed to do, in order to make it easier
to discuss their structure :-)

The main reason for their existence is access checking. In the very first
drafts of the new sam interface, there were no preparations for access
checking. So either this had to be done with (un)become_root and unix
permission checks, or all access checks had be done in the levels above the
the sam interface. Obviously both concepts have some major drawbacks, and it
was tried to incorperate permission checking within the sam db to assure
that all functions, no matter from where they are called, are properly
checked in a consistant way, without loosing the flexibility of nt checks.
The system of handles is somewhat in allignement with the way MSRPC does its
authorisation and was chosen to harmonize with it as far as possible.
In order to manipulate any object in an MS SAM over MSRPC, you need to do an
open call. This open call will return a handle to you that identifies both
the object and you wanting to manipulate it. Apart from the object that is
to be opened,  a desired access must be specified in the open call. This
desired access is checked once (at open time) against the ACL of the object
and if granted, associated with the handle in order to determine later

The same thing applies to the sam interface proposed in
SAM-Interface-handles.txt. The sam_get_user_by_* functions correspond to the
open calls. You (the caller) specify which object you want to manipulate
(i.e SID or name) and retrieve a handle. In addition you need to specify the
permissions you request to be allowed to do and the credentials of the
caller (NT_USER_TOKEN). These are stored in the handle and therefore need
not be specified in every get / set function of the object.

So now back to the structure of the handles. As mentioned before, I don't
think it has actually been decided upon (but perhaps I'm just not aware of
it). All opinions with reasons are therefore very welcome. Personally, I can
think of three different possibilities. The first possibility is a real
handle, i.e. a simple integer that is used as a lookup key. The second
possibility is to fully specify the structure including all data fields of
the associated object (i.e. something like the current SAM_ACCOUNT). And the
third possibility would be a void pointer to a piece of data every sam
backend defines for itself. However the handle is always passed back to the
caller, so that if it is a simple variable SAM_USER_HANDLE *user is enough.
For a pointer type handle SAM_USER_HANDLE **user is needed.

Hopefully this clarifies the situation a little and helps to find a suitable
implementation for the handles.

> -NTSTATUS sam_{get,set}_user_kickoff_time(SAM_USER_HANDLE *user, NTTIME
> -NTSTATUS sam_{get,set}_user_pwd_last_set(SAM_USER_HANDLE *user, NTTIME
> -NTSTATUS sam_{get,set}_user_pwd_can_change(SAM_USER_HANDLE *user, NTTIME
> -NTSTATUS sam_{get,set}_user_pwd_must_change(SAM_USER_HANDLE *user, NTTIME
> +NTSTATUS sam_{get,set}_user_kickoff_time(SAM_USER_HANDLE *user, NTTIME
> +NTSTATUS sam_{get,set}_user_pwd_last_set(SAM_USER_HANDLE *user, NTTIME
> +NTSTATUS sam_{get,set}_user_pwd_can_change(SAM_USER_HANDLE *user, NTTIME
> +NTSTATUS sam_{get,set}_user_pwd_must_change(SAM_USER_HANDLE *user, NTTIME

Both versions are imho correct. It depends upon if they are get or set
routines. The set routines don't need to be pointers, as they pass a value
to the function, the get routines however do need to be pointers in order to
get the values from the db. The SAM_USER_HANDLE is always supplied by the
caller and passed to the function. See the above points for for

> Btw.  What *exactly* do the NT_USER_TOKEN's do? Still don't get it :-/

The NT_USER_TOKEN is one of the parameters passed to se_access_check to
identify the user and test permissions against NT ACLs. It is defined in
include/smb.h but reading Richard Sharps response tells you just as much :-)

> Jelmer


P.S. perhaps adding const all along would make it clear which parameters are
"in parameters" and which are "out paramters"

More information about the samba-technical mailing list