source: branches/samba-3.2.x/source/passdb/secrets.c@ 536

Last change on this file since 536 was 137, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0rc2

File size: 34.4 KB
Line 
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
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22/* the Samba secrets database stores any generated, private information
23 such as the local SID and machine trust password */
24
25#include "includes.h"
26
27#undef DBGC_CLASS
28#define DBGC_CLASS DBGC_PASSDB
29
30static struct db_context *db_ctx;
31
32/* Urrrg. global.... */
33bool global_machine_password_needs_changing;
34
35/**
36 * Use a TDB to store an incrementing random seed.
37 *
38 * Initialised to the current pid, the very first time Samba starts,
39 * and incremented by one each time it is needed.
40 *
41 * @note Not called by systems with a working /dev/urandom.
42 */
43static void get_rand_seed(int *new_seed)
44{
45 *new_seed = sys_getpid();
46 if (db_ctx) {
47 dbwrap_change_int32_atomic(db_ctx, "INFO/random_seed",
48 new_seed, 1);
49 }
50}
51
52/* open up the secrets database */
53bool secrets_init(void)
54{
55 char *fname = NULL;
56 unsigned char dummy;
57
58 if (db_ctx != NULL)
59 return True;
60
61 fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb",
62 lp_private_dir());
63 if (fname == NULL) {
64 return false;
65 }
66
67 db_ctx = db_open_trans(NULL, fname, 0,
68 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
69
70 if (db_ctx == NULL) {
71 DEBUG(0,("Failed to open %s\n", fname));
72 TALLOC_FREE(fname);
73 return False;
74 }
75
76 TALLOC_FREE(fname);
77
78 /**
79 * Set a reseed function for the crypto random generator
80 *
81 * This avoids a problem where systems without /dev/urandom
82 * could send the same challenge to multiple clients
83 */
84 set_rand_reseed_callback(get_rand_seed);
85
86 /* Ensure that the reseed is done now, while we are root, etc */
87 generate_random_buffer(&dummy, sizeof(dummy));
88
89 return True;
90}
91
92struct db_context *secrets_db_ctx(void)
93{
94 if (!secrets_init()) {
95 return NULL;
96 }
97
98 return db_ctx;
99}
100
101/*
102 * close secrets.tdb
103 */
104void secrets_shutdown(void)
105{
106 TALLOC_FREE(db_ctx);
107}
108
109/* read a entry from the secrets database - the caller must free the result
110 if size is non-null then the size of the entry is put in there
111 */
112void *secrets_fetch(const char *key, size_t *size)
113{
114 TDB_DATA dbuf;
115 void *result;
116
117 if (!secrets_init()) {
118 return NULL;
119 }
120
121 if (db_ctx->fetch(db_ctx, talloc_tos(), string_tdb_data(key),
122 &dbuf) != 0) {
123 return NULL;
124 }
125
126 result = memdup(dbuf.dptr, dbuf.dsize);
127 if (result == NULL) {
128 return NULL;
129 }
130 TALLOC_FREE(dbuf.dptr);
131
132 if (size) {
133 *size = dbuf.dsize;
134 }
135
136 return result;
137}
138
139/* store a secrets entry
140 */
141bool secrets_store(const char *key, const void *data, size_t size)
142{
143 NTSTATUS status;
144
145 if (!secrets_init()) {
146 return false;
147 }
148
149 status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
150 make_tdb_data((const uint8 *)data, size),
151 TDB_REPLACE);
152 return NT_STATUS_IS_OK(status);
153}
154
155
156/* delete a secets database entry
157 */
158bool secrets_delete(const char *key)
159{
160 NTSTATUS status;
161 if (!secrets_init()) {
162 return false;
163 }
164
165 status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
166
167 return NT_STATUS_IS_OK(status);
168}
169
170/**
171 * Form a key for fetching the domain sid
172 *
173 * @param domain domain name
174 *
175 * @return keystring
176 **/
177static const char *domain_sid_keystr(const char *domain)
178{
179 char *keystr;
180
181 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
182 SECRETS_DOMAIN_SID, domain);
183 SMB_ASSERT(keystr != NULL);
184 return keystr;
185}
186
187bool secrets_store_domain_sid(const char *domain, const DOM_SID *sid)
188{
189 bool ret;
190
191 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(DOM_SID));
192
193 /* Force a re-query, in case we modified our domain */
194 if (ret)
195 reset_global_sam_sid();
196 return ret;
197}
198
199bool secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
200{
201 DOM_SID *dyn_sid;
202 size_t size = 0;
203
204 dyn_sid = (DOM_SID *)secrets_fetch(domain_sid_keystr(domain), &size);
205
206 if (dyn_sid == NULL)
207 return False;
208
209 if (size != sizeof(DOM_SID)) {
210 SAFE_FREE(dyn_sid);
211 return False;
212 }
213
214 *sid = *dyn_sid;
215 SAFE_FREE(dyn_sid);
216 return True;
217}
218
219bool secrets_store_domain_guid(const char *domain, struct GUID *guid)