New sam system

Kai Krueger kai at
Mon Aug 19 11:24:01 GMT 2002

From: "Kai Krueger" <kai at>  Sent: Wednesday, July 31, 2002
10:21 PM

> 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
> 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
> 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
> caller, so that if it is a simple variable SAM_USER_HANDLE *user is
> For a pointer type handle SAM_USER_HANDLE **user is needed.
> Hopefully this clarifies the situation a little and helps to find a
> implementation for the handles.

As the definitions of the handles structs are important for implementing
some bits of the new sam infrastructure, I'll retry to get to a consense and
decision by making a (nearly) finished proposal. This suggestion is based as
closely as possible on the structure of sam_passwd in the current passdb
code and the first definitions of such structures in the early versions of
the sam interface with a few minor adoptions to the current handles concept.
The handles suggested are fully specified data structures that are the same
for all backends, but it should probably  not be to difficult to dynamically
allocate the sub structure "private" on a per backend basis if advantages
are seen later on.

typedef struct sam_domain {
 TALLOC_CTX *mem_ctx;
 uint32 access_granted;
 struct sam_methods *current_sam_methods; /* sam_methods creating this
handle */
 void (*free_fn)(struct sam_domain **);
 struct domain_data {
  DOM_SID domain_sid; /*SID of the domain. Should not be changed */
  char *domainname; /* Name of the domain */
  char *servername; /* */
  NTTIME max_passwordage; /* time till next password expiration */
  NTTIME min_passwordage; /* time till password can be changed again */
  NTTIME lockout_duration; /* time till login is allowed again after
  NTTIME reset_count; /* time till bad login counter is reset */
  uint16 min_passwordlength; /* minimum number of characters for a password
  uint16 password_history; /* number of passwords stored in history */
  uint16 lockout_count; /* number of bad login attempts before lockout */
  BOOL force_logoff; /* force logoff after logon hours have expired */
  BOOL login_pswdchange; /* Users need to logon to change their password */
  uint32 num_users; /* number of users in the domain */
  uint32 num_groups; /* number of global groups */
  uint32 num_aliases; /* number of local groups */
 } private;

typedef struct sam_user {
 TALLOC_CTX *mem_ctx;
 uint32 access_granted;
 struct sam_methods *current_sam_methods; /* sam_methods creating this
handle */
 void (*free_fn)(struct sam_user **);
 struct user_data {
  uint32 init_flag;
  NTTIME logon_time; /* logon time */
  NTTIME logoff_time; /* logoff time */
  NTTIME kickoff_time; /* kickoff time */
  NTTIME pass_last_set_time; /* password last set time */
  NTTIME pass_can_change_time; /* password can change time */
  NTTIME pass_must_change_time; /* password must change time */
  char * username; /* username string */
  char * domain; /* Windows Domain name */
  char * full_name; /* user's full name string */
  char * unix_home_dir; /* UNIX home directory string */
  char * home_dir; /* home directory string */
  char * dir_drive; /* home directory drive string */
  char * logon_script; /* logon script string */
  char * profile_path; /* profile path string */
  char * acct_desc; /* user description string */
  char * workstations; /* login from workstations string */
  char * unknown_str; /* don't know what this is, yet. */
  char * munged_dial; /* munged path name and dial-back tel number */
  DOM_SID user_sid; /* Primary User SID */
  DOM_SID group_sid; /* Primary Group SID */
  DATA_BLOB lm_pw; /* .data is Null if no password */
  DATA_BLOB nt_pw; /* .data is Null if no password */
  DATA_BLOB plaintext_pw; /* .data is Null if not available */
  uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
  uint32 unknown_3; /* 0x00ff ffff */
  uint16 logon_divs; /* 168 - number of hours in a week */
  uint32 hours_len; /* normally 21 bytes */
  uint8 hours[MAX_HOURS_LEN];
  uint32 unknown_5; /* 0x0002 0000 */
  uint32 unknown_6; /* 0x0000 04ec */
 } private;

typedef sam_group {
 TALLOC_CTX *mem_ctx;
 uint32 access_granted;
 struct sam_methods *current_sam_methods; /* sam_methods creating this
handle */
 void (*free_fn)(struct sam_group **);
 struct group_data {
  char *name;
  char *comment;
  DOM_SID sid;
  int32 flags; /* specifies if the group is a lokal group or a global group
  uint32 num_members;
 } private;

One thing that might need to be added to SAM_USER_HANDLE is the password and
logon history. (i.e. number of logon failures, time of last failed login and
an ordered password history) Do these belong to the sam, or are they stored
in some form in the netlogon service?

Any other information that is missing for a full SAM implementation?


P.S. this would be a great time to get rid of the unknowns. So if anyone
knows what they could be used for... :-)

More information about the samba-technical mailing list