r9555: More updates. Everything except for secrets.c compiles now..
[ira/wip.git] / source4 / lib / samba3 / secrets.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Andrew Tridgell 1992-2001
4    Copyright (C) Andrew Bartlett      2002
5    Copyright (C) Rafal Szczesniak     2002
6    Copyright (C) Tim Potter           2001
7    Copyright (C) Jelmer Vernooij          2005
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /* the Samba secrets database stores any generated, private information
25    such as the local SID and machine trust password */
26
27 #define SECRETS_DOMAIN_SID "SECRETS/SID"
28 #define SECRETS_DOMAIN_GUID "SECRETS/DOMGUID"
29 #define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW"
30 #define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC"
31 #define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC"
32 #define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD"
33 #define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME"
34 #define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE"
35 #define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE"
36 #define SECRETS_AUTH_USER      "SECRETS/AUTH_USER"
37 #define SECRETS_AUTH_DOMAIN      "SECRETS/AUTH_DOMAIN"
38 #define SECRETS_AUTH_PASSWORD  "SECRETS/AUTH_PASSWORD"
39
40
41 #include "includes.h"
42 #include "tdb.h"
43 #include "system/filesys.h"
44 #include "librpc/gen_ndr/ndr_security.h"
45 #include "lib/tdb/include/tdbutil.h"
46
47 /* structure for storing machine account password
48    (ie. when samba server is member of a domain */
49 struct machine_acct_pass {
50         uint8_t hash[16];
51         time_t mod_time;
52 };
53
54 #define SECRETS_AFS_MAXKEYS 8
55
56 struct afs_key {
57         uint32_t kvno;
58         char key[8];
59 };
60
61 /*
62  * storage structure for trusted domain
63  */
64 typedef struct trusted_dom_pass {
65         size_t uni_name_len;
66         const char *uni_name[32]; /* unicode domain name */
67         size_t pass_len;
68         const char *pass;               /* trust relationship's password */
69         time_t mod_time;
70         struct dom_sid domain_sid;      /* remote domain's sid */
71 } TRUSTED_DOM_PASS;
72
73 /**
74  * Unpack SID into a pointer
75  *
76  * @param pack_buf pointer to buffer with packed representation
77  * @param bufsize size of the buffer
78  * @param sid pointer to sid structure to be filled with unpacked data
79  *
80  * @return size of structure unpacked from buffer
81  **/
82 static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, struct dom_sid* sid)
83 {
84         int idx, len = 0;
85         
86         if (!sid || !pack_buf) return -1;
87
88         len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb",
89                           &sid->sid_rev_num, &sid->num_auths);
90                           
91         for (idx = 0; idx < 6; idx++) {
92                 len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
93         }
94         
95         for (idx = 0; idx < 15; idx++) {
96                 len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
97         }
98         
99         return len;
100 }
101
102 /**
103  * Unpack TRUSTED_DOM_PASS passed by pointer
104  *
105  * @param pack_buf pointer to buffer with packed representation
106  * @param bufsize size of the buffer
107  * @param pass pointer to trusted domain password to be filled with unpacked data
108  *
109  * @return size of structure unpacked from buffer
110  **/
111 static size_t tdb_trusted_dom_pass_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
112 {
113         int idx, len = 0;
114         
115         if (!pack_buf || !pass) return -1;
116
117         /* unpack unicode domain name and plaintext password */
118         len += tdb_unpack(tdb, pack_buf, bufsize - len, "d", &pass->uni_name_len);
119         
120         for (idx = 0; idx < 32; idx++)
121                 len +=  tdb_unpack(tdb, pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]);
122
123         len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass,
124                           &pass->mod_time);
125         
126         /* unpack domain sid */
127         len += tdb_sid_unpack(tdb, pack_buf + len, bufsize - len, &pass->domain_sid);
128         
129         return len;     
130 }
131
132
133 static TDB_CONTEXT *secrets_open(const char *fname)
134 {
135         TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600);
136
137         if (!tdb) {
138                 DEBUG(0,("Failed to open %s\n", fname));
139                 return NULL;
140         }
141
142         return tdb;
143 }
144
145 static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid)
146 {
147         struct dom_sid *dyn_sid;
148         TDB_DATA val;
149         char *key;
150         size_t size;
151
152         asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain);
153         strupper_m(key);
154         
155         val = tdb_fetch_bystring(tdb, key);
156         /* FIXME: Convert val to dyn_sid */
157         SAFE_FREE(key);
158
159         if (dyn_sid == NULL)
160                 return False;
161
162         if (size != sizeof(struct dom_sid))
163         { 
164                 SAFE_FREE(dyn_sid);
165                 return False;
166         }
167
168         *sid = *dyn_sid;
169         SAFE_FREE(dyn_sid);
170         return True;
171 }
172
173 static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, struct GUID *guid)
174 {
175         struct GUID *dyn_guid;
176         char *key;
177         TDB_DATA val;
178         size_t size;
179
180         asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain);
181         strupper_m(key);
182         val = tdb_fetch_bystring(tdb, key);
183
184         dyn_guid = (struct GUID *)val.dptr;
185
186         if (!dyn_guid) {
187                 return False;
188         }
189
190         if (val.dsize != sizeof(struct GUID))
191         { 
192                 DEBUG(1,("GUID size %d is wrong!\n", (int)size));
193                 SAFE_FREE(dyn_guid);
194                 return False;
195         }
196
197         *guid = *dyn_guid;
198         SAFE_FREE(dyn_guid);
199         return True;
200 }
201
202 /**
203  * Form a key for fetching the machine trust account password
204  *
205  * @param domain domain name
206  *
207  * @return stored password's key
208  **/
209 static char *trust_keystr(const char *domain)
210 {
211         char *keystr;
212
213         asprintf(&keystr, "%s/%s", SECRETS_MACHINE_ACCT_PASS, domain);
214         strupper_m(keystr);
215
216         return keystr;
217 }
218
219 /**
220  * Form a key for fetching a trusted domain password
221  *
222  * @param domain trusted domain name
223  *
224  * @return stored password's key
225  **/
226 static char *trustdom_keystr(const char *domain)
227 {
228         char *keystr;
229
230         asprintf(&keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain);
231         strupper_m(keystr);
232                 
233         return keystr;
234 }
235
236 /************************************************************************
237  Routine to get the trust account password for a domain.
238  The user of this function must have locked the trust password file using
239  the above secrets_lock_trust_account_password().
240 ************************************************************************/
241
242 static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, 
243                                           const char *domain, uint8_t ret_pwd[16],
244                                           time_t *pass_last_set_time,
245                                           uint32_t *channel)
246 {
247         struct machine_acct_pass *pass;
248         char *plaintext;
249         TDB_DATA val;
250
251         plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time, 
252                                                    channel);
253         if (plaintext) {
254                 DEBUG(4,("Using cleartext machine password\n"));
255                 E_md4hash(plaintext, ret_pwd);
256                 SAFE_FREE(plaintext);
257                 return True;
258         }
259         
260         val = tdb_fetch_bystring(tdb, trust_keystr(domain));
261         if (!val.dptr) {
262                 DEBUG(5, ("tdb_fetch_bystring failed!\n"));
263                 return False;
264         }
265         
266         if (val.dsize != sizeof(*pass)) {
267                 DEBUG(0, ("secrets were of incorrect size!\n"));
268                 return False;
269         }
270
271         pass = (struct machine_acct_pass *)val.dptr;
272
273         if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
274         memcpy(ret_pwd, pass->hash, 16);
275
276         return True;
277 }
278
279 /************************************************************************
280  Routine to get account password to trusted domain
281 ************************************************************************/
282
283 static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time)
284 {
285         struct trusted_dom_pass pass;
286         
287         /* unpacking structures */
288         int pass_len = 0;
289         TDB_DATA val;
290
291         ZERO_STRUCT(pass);
292
293         /* fetching trusted domain password structure */
294         val = tdb_fetch_bystring(tdb, trustdom_keystr(domain));
295         if (!val.dptr) {
296                 DEBUG(5, ("secrets_fetch failed!\n"));
297                 return False;
298         }
299
300         /* unpack trusted domain password */
301         pass_len = tdb_trusted_dom_pass_unpack(val.dptr, val.dsize, &pass);
302
303         if (pass_len != val.dsize) {
304                 DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
305                 return False;
306         }
307                         
308         /* the trust's password */      
309         if (pwd) {
310                 *pwd = strdup(pass.pass);
311                 if (!*pwd) {
312                         return False;
313                 }
314         }
315
316         /* last change time */
317         if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
318
319         /* domain sid */
320         
321         *sid = dom_sid_dup(tdb, &pass.domain_sid);
322                 
323         return True;
324 }
325
326 /************************************************************************
327  Routine to fetch the plaintext machine account password for a realm
328 the password is assumed to be a null terminated ascii string
329 ************************************************************************/
330 static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain, 
331                                      time_t *pass_last_set_time,
332                                      uint32_t *channel)
333 {
334         char *key = NULL;
335         char *ret;
336         TDB_DATA val;
337         asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
338         strupper_m(key);
339         val = tdb_fetch_bystring(tdb, key);
340         SAFE_FREE(key);
341         
342         if (pass_last_set_time) {
343                 asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
344                 strupper_m(key);
345                 tdb_fetch_uint32(tdb, key, (uint32_t *)pass_last_set_time);
346                 SAFE_FREE(key);
347         }
348         
349         if (channel) {
350                 asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
351                 strupper_m(key);
352                 tdb_fetch_uint32(tdb, key, channel);
353                 SAFE_FREE(key);
354         }
355         
356         return ret;
357 }
358
359 /*******************************************************************
360  find the ldap password
361 ******************************************************************/
362 static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw)
363 {
364         char *key = NULL;
365         size_t size;
366         TDB_DATA val;
367         
368         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
369                 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
370         }
371         
372         val = tdb_fetch_bystring(tdb, key);
373         *pw = val.dptr;
374         SAFE_FREE(key);
375
376         if (!size) {
377                 return False;
378         }
379         
380         return True;
381 }
382
383
384 /**
385  * Get trusted domains info from secrets.tdb.
386  *
387  * The linked list is allocated on the supplied talloc context, caller gets to destroy
388  * when done.
389  *
390  * @param ctx Allocation context
391  * @param enum_ctx Starting index, eg. we can start fetching at third
392  *        or sixth trusted domain entry. Zero is the first index.
393  *        Value it is set to is the enum context for the next enumeration.
394  * @param num_domains Number of domain entries to fetch at one call
395  * @param domains Pointer to array of trusted domain structs to be filled up
396  *
397  * @return nt status code of rpc response
398  **/ 
399
400 static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
401                                      int *num_domains, struct samba3_trustdom ***domains)
402 {
403         TDB_LIST_NODE *keys, *k;
404         struct samba3_trustdom *dom = NULL;
405         char *pattern;
406         unsigned int start_idx;
407         uint32_t idx = 0;
408         size_t size, packed_size = 0;
409         fstring dom_name;
410         char *packed_pass;
411         struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass);
412         NTSTATUS status;
413
414         if (!pass) {
415                 DEBUG(0, ("talloc_zero failed!\n"));
416                 return NT_STATUS_NO_MEMORY;
417         }
418                                 
419         *num_domains = 0;
420         start_idx = *enum_ctx;
421
422         /* generate searching pattern */
423         if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
424                 DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
425                 return NT_STATUS_NO_MEMORY;
426         }
427
428         DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", 
429                   max_num_domains, *enum_ctx));
430
431         *domains = talloc_zero_array(ctx, struct samba3_trustdom *, max_num_domains);
432
433         /* fetching trusted domains' data and collecting them in a list */
434         keys = tdb_search_keys(tdb, pattern);
435
436         /* 
437          * if there's no keys returned ie. no trusted domain,
438          * return "no more entries" code
439          */
440         status = NT_STATUS_NO_MORE_ENTRIES;
441
442         /* searching for keys in secrets db -- way to go ... */
443         for (k = keys; k; k = k->next) {
444                 char *secrets_key;
445                 
446                 /* important: ensure null-termination of the key string */
447                 secrets_key = strndup(k->node_key.dptr, k->node_key.dsize);
448                 if (!secrets_key) {
449                         DEBUG(0, ("strndup failed!\n"));
450                         return NT_STATUS_NO_MEMORY;
451                 }
452
453                 packed_pass = secrets_fetch(tdb, secrets_key, &size);
454                 packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
455                 /* packed representation isn't needed anymore */
456                 SAFE_FREE(packed_pass);
457                 
458                 if (size != packed_size) {
459                         DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
460                         continue;
461                 }
462                 
463                 pull_ucs2_fstring(dom_name, pass->uni_name);
464                 DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
465                            idx, dom_name, sid_string_static(&pass->domain_sid)));
466
467                 SAFE_FREE(secrets_key);
468
469                 if (idx >= start_idx && idx < start_idx + max_num_domains) {
470                         dom = talloc(ctx, struct samba3_trustdom);
471                         if (!dom) {
472                                 /* free returned tdb record */
473                                 return NT_STATUS_NO_MEMORY;
474                         }
475                         
476                         /* copy domain sid */
477                         SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
478                         memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
479                         
480                         /* copy unicode domain name */
481                         dom->name = talloc_memdup(ctx, pass->uni_name,
482                                                   (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t));
483                         
484                         (*domains)[idx - start_idx] = dom;
485                         
486                         DEBUG(18, ("Secret record is in required range.\n \
487                                    start_idx = %d, max_num_domains = %d. Added to returned array.\n",
488                                    start_idx, max_num_domains));
489
490                         *enum_ctx = idx + 1;
491                         (*num_domains)++;
492                 
493                         /* set proper status code to return */
494                         if (k->next) {
495                                 /* there are yet some entries to enumerate */
496                                 status = STATUS_MORE_ENTRIES;
497                         } else {
498                                 /* this is the last entry in the whole enumeration */
499                                 status = NT_STATUS_OK;
500                         }
501                 } else {
502                         DEBUG(18, ("Secret is outside the required range.\n \
503                                    start_idx = %d, max_num_domains = %d. Not added to returned array\n",
504                                    start_idx, max_num_domains));
505                 }
506                 
507                 idx++;          
508         }
509         
510         DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains));
511
512         /* free the results of searching the keys */
513         tdb_search_list_free(keys);
514
515         return status;
516 }
517
518 /*******************************************************************************
519  Fetch the current (highest) AFS key from secrets.tdb
520 *******************************************************************************/
521 static BOOL secrets_fetch_afs_key(TDB_CONTEXT *tdb, const char *cell, struct afs_key *result)
522 {
523         fstring key;
524         struct afs_keyfile *keyfile;
525         size_t size;
526         uint32_t i;
527
528         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
529
530         keyfile = (struct afs_keyfile *)secrets_fetch(tdb, key, &size);
531
532         if (keyfile == NULL)
533                 return False;
534
535         if (size != sizeof(struct afs_keyfile)) {
536                 SAFE_FREE(keyfile);
537                 return False;
538         }
539
540         i = ntohl(keyfile->nkeys);
541
542         if (i > SECRETS_AFS_MAXKEYS) {
543                 SAFE_FREE(keyfile);
544                 return False;
545         }
546
547         *result = keyfile->entry[i-1];
548
549         result->kvno = ntohl(result->kvno);
550
551         return True;
552 }
553
554 /******************************************************************************
555   When kerberos is not available, choose between anonymous or
556   authenticated connections.  
557
558   We need to use an authenticated connection if DCs have the
559   RestrictAnonymous registry entry set > 0, or the "Additional
560   restrictions for anonymous connections" set in the win2k Local
561   Security Policy.
562
563   Caller to free() result in domain, username, password
564 *******************************************************************************/
565 static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char **domain, char **password)
566 {
567         *username = secrets_fetch(tdb, SECRETS_AUTH_USER, NULL);
568         *domain = secrets_fetch(tdb, SECRETS_AUTH_DOMAIN, NULL);
569         *password = secrets_fetch(tdb, SECRETS_AUTH_PASSWORD, NULL);
570         
571         if (*username && **username) {
572
573                 if (!*domain || !**domain)
574                         *domain = smb_xstrdup(lp_workgroup());
575                 
576                 if (!*password || !**password)
577                         *password = smb_xstrdup("");
578
579                 DEBUG(3, ("IPC$ connections done by user %s\\%s\n", 
580                           *domain, *username));
581
582         } else {
583                 DEBUG(3, ("IPC$ connections done anonymously\n"));
584                 *username = smb_xstrdup("");
585                 *domain = smb_xstrdup("");
586                 *password = smb_xstrdup("");
587         }
588 }
589
590