This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[tprouty/samba.git] / docs / docbook / devdoc / sam.sgml
1 <chapter id="sam">
2
3 <chapterinfo>
4         <author>
5                 <firstname>Andrew</firstname><surname>Bartlett</surname>
6         </author>
7         <pubdate>1 October 2002</pubdate>
8 </chapterinfo>
9
10 <title>The Upcoming SAM System</title>
11
12 <sect1>
13 <title>Security in the 'new SAM'</title>
14
15 <para>One of the biggest problems with passdb is it's implementation of
16 'security'.  Access control is on a 'are you root at the moment' basis,
17 and it has no concept of NT ACLs.  Things like ldapsam had to add
18 'magic' 'are you root' checks.</para>
19
20 <para>We took this very seriously when we started work, and the new structure
21 is designed with this in mind, from the ground up.  Each call to the SAM
22 has a NT_TOKEN and (if relevant) an 'access desired'.  This is either
23 provided as a parameter, or implicitly supplied by the object being
24 accessed.</para>
25
26 <para>
27 For example, when you call 
28 </para>
29
30 <programlisting><
31 NTSTATUS sam_get_account_by_name(const SAM_CONTEXT *context, const
32 NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain,
33 const char *name, SAM_ACCOUNT_HANDLE **account)
34 </programlisting>
35
36 <para>
37 The context can be NULL (and is used to allow import/export by setting
38 up 2 contexts, and allowing calls on both simultaneously)
39 </para>
40
41 <para>
42 The access token *must* be specified.  Normally the user's token out of
43 current_user, this can also be a global 'system' context.
44 </para>
45
46 <para>
47 The access desired is as per the ACL, for passing to the seaccess stuff.
48 </para>
49
50 <para>
51 The domain/username are standard.  Even if we only have one domain,
52 keeping this ensures that we don't get 'unqualified' usernames (same
53 problem as we had with unqualified SIDs).
54 </para>
55
56 <para>
57 We return a 'handle'.  This is opaque to the rest of Samba, but is
58 operated on by get/set routines, all of which return NTSTATUS.
59 </para>
60
61 <para>
62 The access checking is done by the SAM module.   The reason it is not
63 done 'above' the interface is to ensure a 'choke point'.  I put a lot of
64 effort into the auth subsystem to ensure we never 'accidentally' forgot
65 to check for null passwords, missed a restriction etc.  I intend the SAM
66 to be written with the same caution.
67 </para>
68
69 <para>
70 The reason the access checking is not handled by the interface itself is
71 due to the different implementations it make take on.  For example, on
72 ADS, you cannot set a password over a non-SSL connection.  Other
73 backends may have similar requirements - we need to leave this policy up
74 to the modules.  They will naturally have access to 'helper' procedures
75 and good examples to avoid mishaps.
76 </para>
77
78 <para>
79 (Furthermore, some backends my actually chose to push the whole ACL
80 issue to the remote server, and - assuming ldap for this example - bind
81 as the user directly)
82 </para>
83
84 <para>
85 Each returned handle has an internal 'access permitted', which allows
86 the 'get' and 'set' routines to return 'ACCESS_DENIED' for things that
87 were not able to be retrieved from the backend.  This removes the need
88 to specify the NT_TOKEN on every operation, and allows for 'object not
89 present' to be easily distinguished from 'access denied'.
90 </para>
91
92 <para>
93 When you 'set' an object (calling sam_update_account) the internal
94 details are again used.  Each change that has been made to the object
95 has been flagged, so as to avoid race conditions (on unmodified
96 components) and to avoid violating any extra ACL requirements on the
97 actual data store (like the LDAP server).
98 </para>
99
100 <para>
101 Finally, we have generic get_sec_desc() and set_sec_desc() routines to
102 allow external ACL manipulation.  These do lookups based on SID.
103 </para>
104
105 </sect1>
106
107 <sect1>
108 <title>Standalone from UNIX</title>
109
110 <para>
111 One of the primary tenants of the 'new SAM' is that it would not attempt
112 to deal with 'what unix id for that'.  This would be left to the 'SMS'
113 (Sid Mapping System') or SID farm, and probably administered via
114 winbind.  We have had constructive discussion on how 'basic' unix
115 accounts like 'root' would be handled, and we think this can work.  
116 Accounts not preexisting in unix would be served up via winbind.
117 </para>
118
119 <para>
120 This is an *optional* part, and my preferred end-game.  We have a fare
121 way to go before things like winbind up to it however.
122 </para>
123
124 </sect1>
125
126 <sect1>
127 <title>Handles and Races in the new SAM</title>
128
129 <para>
130 One of the things that the 'new SAM' work has tried to face is both
131 compatibility with existing code, and a closer alignment to the SAMR
132 interface.  I consider SAMR to be a 'primary customer' to the this work,
133 because if we get alignment with that wrong, things get more, rather
134 than less complex.  Also, most other parts of Samba are much more
135 flexible with what they can allow.
136 </para>
137
138 <para>
139 In any case, that was a decision taken as to how the general design
140 would progress.  BTW, my understanding of SAMR may be completely flawed.
141 </para>
142
143 <para>
144 One of the most race-prone areas of the new code is the conflicting
145 update problem.  We have taken two approaches:  
146 </para>
147
148 <itemizedlist>
149 <listitem>
150 <para>'Not conflicting' conflicts.  Due to the way usrmgr operates, it will
151 open a user, display all the properties and *save* them all, even if you
152 don't change any.
153 </para>
154
155 <para>
156 For this, see what I've done in rpc_server/srv_samr_util.c.  I intend
157 to take this one step further, and operate on the 'handle' that the
158 values were read from.  This should mean that we only update things that
159 have *really* changed.
160 </para>
161 </listitem>
162
163 <listitem>
164 <para>
165 'conflicting' updates:  Currently we don't deal with this (in passdb
166 or the new sam stuff), but the design is sufficiently flexible to 'deny'
167 a second update.  I don't foresee locking records however.
168 </para>
169 </listitem>
170 </itemizedlist>
171
172 </sect1>
173
174 <sect1>
175 <title>Layers</title>
176
177 <sect2>
178 <title>Application</title>
179
180 <para>
181 This is where smbd, samtest and whatever end-user replacement we have
182 for pdbedit sits.  They use only the SAM interface, and do not get
183 'special knowledge' of what is below them.
184 </para>
185
186 <sect2>
187 <title>SAM Interface</title>
188
189 <para>
190 This level 'owns' the various handle structures, the get/set routines on
191 those structures and provides the public interface.  The application
192 layer may initialize a 'context' to be passed to all interface routines,
193 else a default, self-initialising context will be supplied.  This layser
194 finds the appropriate backend module for the task, and tries very hard
195 not to need to much 'knowledge'.  It should just provide the required
196 abstraction to the modules below, and arrange for their initial loading.
197 </para>
198
199 <para>
200 We could possibly add ACL checking at this layer, to avoid discrepancies
201 in implementation modules.
202 </para>
203
204 </sect2>
205
206 <sect2>
207 <title>SAM Modules</title>
208
209 <para>
210 These do not communicate with the application directly, only by setting
211 values in the handles, and receiving requests from the interface.  These
212 modules are responsible for translating values from the handle's
213 .private into (say) an LDAP modification list.  The module is expected
214 to 'know' things like it's own domain SID, domain name, and any other
215 state attached to the SAM.  Simpler modules may call back to some helper
216 routine.
217 </para>
218
219 </sect2>
220 </sect1>
221
222 <sect1>
223 <title>SAM Modules</title>
224
225 <sect2>
226 <title>Special Module: sam_passdb</title>
227
228 <para>
229 In order for there to be a smooth transition, kai is writing a module
230 that reads existing passdb backends, and translates them into SAM
231 replies.  (Also pulling data from the account policy DB etc).  We also
232 intend to write a module that does the reverse - gives the SAM a passdb
233 interface.
234 </para>
235 </sect2>
236
237 <sect2>
238 <title>sam_ads</title>
239 <para>
240 This is the first of the SAM modules to be committed to the tree -
241 mainly because I needed to coordinate work with metze (who authored most
242 of it).  This module aims to use Samba's libads code to provide an
243 Active Directory LDAP client, suitable for use on a mixed-mode DC. 
244 While it is currently being tested against Win2k servers (with a
245 password in the smb.conf file) it is expected to eventually use a
246 (possibly modified) OpenLDAP server.  We hope that this will assist in
247 the construction of an Samba AD DC.
248 </para>
249
250 <para>
251 We also intend to construct a Samba 2.2/3.0 compatible ldap module,
252 again using libads code.
253 </para>
254 </sect2>
255 </sect1>
256
257 <sect1>
258 <title>Memory Management</title>
259
260 <para> 
261 The 'new SAM' development effort also concerned itself with getting a
262 sane implementation of memory management.  It was decided that we would
263 be (as much as possible) talloc based, using an 'internal talloc
264 context' on many objects.  That is, the creation of an object would
265 initiate it's own internal talloc context, and this would be used for
266 all operations on that object.  Much of this is already implemented in
267 passdb.  Also, like passdb, it will be possible to specify that some
268 object actually be created on a specified context.  
269 </para>
270
271 <para>
272 Memory management is important here because the APIs in the 'new SAM' do
273 not use 'pdb_init()' or an equivalent.  They always allocate new
274 objects.  Enumeration's are slightly different, and occur on a supplied
275 context that 'owns' the entire list, rather than per-element.  (the
276 enumeration functions return an array of all elements - not full handles
277 just basic (and public) info)  Likewise for things that fill in a char
278 **.
279 </para>
280
281 <para>For example:</para>
282
283 <para><programlisting>
284 NTSTATUS sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN
285 *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name,
286 uint32 *type)
287 </programlisting></para>
288
289 <para>Takes a context to allocate the 'name' on, while:</para>
290
291 <para><programlisting>
292 NTSTATUS sam_get_account_by_sid(const SAM_CONTEXT *context, const
293 NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID
294 *accountsid, SAM_ACCOUNT_HANDLE **account)
295 </programlisting></para>
296
297 <para>Allocates a handle and stores the allocation context on that handle.</para>
298
299 <para>I think that the following:</para>
300
301 <para><programlisting>
302 NTSTATUS sam_enum_accounts(const SAM_CONTEXT *context, const
303 NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 acct_ctrl,
304 int32 *account_count, SAM_ACCOUNT_ENUM **accounts)
305 </programlisting></para>
306
307 </sect1>
308
309 <sect1>
310 <title>Testing</title>
311
312 <para>
313 Testing is vital in any piece of software, and Samba is certainly no
314 exception. In designing this new subsystem, we have taken care to ensure
315 it is easily tested, independent of outside protocols.
316 </para>
317
318 <para>
319 To this end, Jelmer has constructed 'samtest'.  
320 </para>
321
322 <para>
323 This utility (see torture/samtest.c) is structured like rpcclient, but
324 instead operates on the SAM subsystem.  It creates a 'custom' SAM
325 context, that may be distinct from the default values used by the rest
326 of the system, and can load a separate configuration file.  
327 </para>
328
329 <para>
330 A small number of commands are currently implemented, but these have
331 already proved vital in testing.   I expect SAM module authors will find
332 it particularly valuable.
333 </para>
334
335 <para>Example useage:</para>
336
337 <para><prompt>$</prompt> <command>bin/samtest</command></para>
338
339 <para><programlisting>
340 > context ads:ldap://192.168.1.96
341 </programlisting>
342 (this loads a new context, using the new ADS module.  The parameter is
343 the 'location' of the ldap server)
344 </para>
345
346 <para><programlisting>
347 > lookup_name DOMAIN abartlet
348 </programlisting>
349 (returns a sid).
350 </para>
351
352 <para>
353 Because the 'new SAM' is NT ACL based, there will be a command to
354 specify an arbitrary NT ACL, but for now it uses 'system' by default.
355 </para>
356 </sect1>
357 </chapter>