source: trunk/server/libcli/auth/schannel_state_tdb.c

Last change on this file was 916, checked in by Silvan Scherrer, 9 years ago

Samba Server: update trunk to version 3.6.25, fix some more crlf issues

File size: 9.1 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 module to store/fetch session keys for the schannel server
5
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009
8 Copyright (C) Guenther Deschner 2009
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "system/filesys.h"
26#include <tdb.h>
27#include "../lib/util/util_tdb.h"
28#include "../libcli/auth/schannel.h"
29#include "../librpc/gen_ndr/ndr_schannel.h"
30#include "lib/util/tdb_wrap.h"
31
32#define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL"
33
34/******************************************************************************
35 Open or create the schannel session store tdb. Non-static so it can
36 be called from parent processes to corectly handle TDB_CLEAR_IF_FIRST
37*******************************************************************************/
38
39struct tdb_wrap *open_schannel_session_store(TALLOC_CTX *mem_ctx,
40 const char *private_dir)
41{
42 struct tdb_wrap *tdb_sc = NULL;
43 char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", private_dir);
44
45 if (!fname) {
46 return NULL;
47 }
48
49 tdb_sc = tdb_wrap_open(mem_ctx, fname, 0, TDB_CLEAR_IF_FIRST|TDB_NOSYNC, O_RDWR|O_CREAT, 0600);
50
51 if (!tdb_sc) {
52 DEBUG(0,("open_schannel_session_store: Failed to open %s - %s\n",
53 fname, strerror(errno)));
54 TALLOC_FREE(fname);
55 return NULL;
56 }
57
58 TALLOC_FREE(fname);
59
60 return tdb_sc;
61}
62
63/********************************************************************
64 ********************************************************************/
65
66static
67NTSTATUS schannel_store_session_key_tdb(struct tdb_wrap *tdb_sc,
68 TALLOC_CTX *mem_ctx,
69 struct netlogon_creds_CredentialState *creds)
70{
71 enum ndr_err_code ndr_err;
72 DATA_BLOB blob;
73 TDB_DATA value;
74 int ret;
75 char *keystr;
76 char *name_upper;
77
78 name_upper = strupper_talloc(mem_ctx, creds->computer_name);
79 if (!name_upper) {
80 return NT_STATUS_NO_MEMORY;
81 }
82
83 keystr = talloc_asprintf(mem_ctx, "%s/%s",
84 SECRETS_SCHANNEL_STATE, name_upper);
85 TALLOC_FREE(name_upper);
86 if (!keystr) {
87 return NT_STATUS_NO_MEMORY;
88 }
89
90 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, creds,
91 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
92 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
93 talloc_free(keystr);
94 return ndr_map_error2ntstatus(ndr_err);
95 }
96
97 value.dptr = blob.data;
98 value.dsize = blob.length;
99
100 ret = tdb_store_bystring(tdb_sc->tdb, keystr, value, TDB_REPLACE);
101 if (ret != TDB_SUCCESS) {
102 DEBUG(0,("Unable to add %s to session key db - %s\n",
103 keystr, tdb_errorstr(tdb_sc->tdb)));
104 talloc_free(keystr);
105 return NT_STATUS_INTERNAL_DB_CORRUPTION;
106 }
107
108 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
109 keystr));
110
111 if (DEBUGLEVEL >= 10) {
112 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
113 }
114
115 talloc_free(keystr);
116
117 return NT_STATUS_OK;
118}
119
120/********************************************************************
121 ********************************************************************/
122
123static
124NTSTATUS schannel_fetch_session_key_tdb(struct tdb_wrap *tdb_sc,
125 TALLOC_CTX *mem_ctx,
126 const char *computer_name,
127 struct netlogon_creds_CredentialState **pcreds)
128{
129 NTSTATUS status;
130 TDB_DATA value;
131 enum ndr_err_code ndr_err;
132 DATA_BLOB blob;
133 struct netlogon_creds_CredentialState *creds = NULL;
134 char *keystr = NULL;
135 char *name_upper;
136
137 *pcreds = NULL;
138
139 name_upper = strupper_talloc(mem_ctx, computer_name);
140 if (!name_upper) {
141 return NT_STATUS_NO_MEMORY;
142 }
143
144 keystr = talloc_asprintf(mem_ctx, "%s/%s",
145 SECRETS_SCHANNEL_STATE, name_upper);
146 TALLOC_FREE(name_upper);
147 if (!keystr) {
148 return NT_STATUS_NO_MEMORY;
149 }
150
151 value = tdb_fetch_bystring(tdb_sc->tdb, keystr);
152 if (!value.dptr) {
153 DEBUG(10,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
154 keystr ));
155 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
156 goto done;
157 }
158
159 creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
160 if (!creds) {
161 status = NT_STATUS_NO_MEMORY;
162 goto done;
163 }
164
165 blob = data_blob_const(value.dptr, value.dsize);
166
167 ndr_err = ndr_pull_struct_blob(&blob, creds, creds,
168 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
169 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
170 status = ndr_map_error2ntstatus(ndr_err);
171 goto done;
172 }
173
174 if (DEBUGLEVEL >= 10) {
175 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
176 }
177
178 DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n",
179 keystr));
180
181 status = NT_STATUS_OK;
182
183 done:
184
185 talloc_free(keystr);
186 SAFE_FREE(value.dptr);
187
188 if (!NT_STATUS_IS_OK(status)) {
189 talloc_free(creds);
190 return status;
191 }
192
193 *pcreds = creds;
194
195 return NT_STATUS_OK;
196}
197
198/******************************************************************************
199 Wrapper around schannel_fetch_session_key_tdb()
200 Note we must be root here.
201*******************************************************************************/
202
203NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx,
204 const char *db_priv_dir,
205 const char *computer_name,
206 struct netlogon_creds_CredentialState **_creds)
207{
208 TALLOC_CTX *tmpctx;
209 struct tdb_wrap *tdb_sc;
210 struct netlogon_creds_CredentialState *creds;
211 NTSTATUS status;
212
213 tmpctx = talloc_named(mem_ctx, 0, "schannel_get_creds_state");
214 if (!tmpctx) {
215 return NT_STATUS_NO_MEMORY;
216 }
217
218 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
219 if (!tdb_sc) {
220 return NT_STATUS_ACCESS_DENIED;
221 }
222
223 status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx,
224 computer_name, &creds);
225 if (NT_STATUS_IS_OK(status)) {
226 *_creds = talloc_steal(mem_ctx, creds);
227 if (!*_creds) {
228 status = NT_STATUS_NO_MEMORY;
229 }
230 }
231
232 talloc_free(tmpctx);
233 return status;
234}
235
236/******************************************************************************
237 Wrapper around schannel_store_session_key_tdb()
238 Note we must be root here.
239*******************************************************************************/
240
241NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx,
242 const char *db_priv_dir,
243 struct netlogon_creds_CredentialState *creds)
244{
245 TALLOC_CTX *tmpctx;
246 struct tdb_wrap *tdb_sc;
247 NTSTATUS status;
248
249 tmpctx = talloc_named(mem_ctx, 0, "schannel_save_creds_state");
250 if (!tmpctx) {
251 return NT_STATUS_NO_MEMORY;
252 }
253
254 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
255 if (!tdb_sc) {
256 return NT_STATUS_ACCESS_DENIED;
257 }
258
259 status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
260
261 talloc_free(tmpctx);
262 return status;
263}
264
265/********************************************************************
266 Validate an incoming authenticator against the credentials for the
267 remote machine stored in the schannel database.
268
269 The credentials are (re)read and from the schannel database, and
270 written back after the caclulations are performed.
271
272 If the creds_out parameter is not NULL returns the credentials.
273 ********************************************************************/
274
275NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
276 const char *db_priv_dir,
277 const char *computer_name,
278 struct netr_Authenticator *received_authenticator,
279 struct netr_Authenticator *return_authenticator,
280 struct netlogon_creds_CredentialState **creds_out)
281{
282 TALLOC_CTX *tmpctx;
283 struct tdb_wrap *tdb_sc;
284 struct netlogon_creds_CredentialState *creds;
285 NTSTATUS status;
286 int ret;
287
288 if (creds_out != NULL) {
289 *creds_out = NULL;
290 }
291
292 tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
293 if (!tmpctx) {
294 return NT_STATUS_NO_MEMORY;
295 }
296
297 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
298 if (!tdb_sc) {
299 status = NT_STATUS_ACCESS_DENIED;
300 goto done;
301 }
302
303 ret = tdb_transaction_start(tdb_sc->tdb);
304 if (ret != 0) {
305 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
306 goto done;
307 }
308
309 /* Because this is a shared structure (even across
310 * disconnects) we must update the database every time we
311 * update the structure */
312
313 status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx,
314 computer_name, &creds);
315 if (!NT_STATUS_IS_OK(status)) {
316 tdb_transaction_cancel(tdb_sc->tdb);
317 goto done;
318 }
319
320 status = netlogon_creds_server_step_check(creds,
321 received_authenticator,
322 return_authenticator);
323 if (!NT_STATUS_IS_OK(status)) {
324 tdb_transaction_cancel(tdb_sc->tdb);
325 goto done;
326 }
327
328 status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
329 if (!NT_STATUS_IS_OK(status)) {
330 tdb_transaction_cancel(tdb_sc->tdb);
331 goto done;
332 }
333
334 tdb_transaction_commit(tdb_sc->tdb);
335
336 if (creds_out) {
337 *creds_out = talloc_steal(mem_ctx, creds);
338 if (!*creds_out) {
339 status = NT_STATUS_NO_MEMORY;
340 goto done;
341 }
342 }
343
344 status = NT_STATUS_OK;
345
346done:
347 talloc_free(tmpctx);
348 return status;
349}
350
Note: See TracBrowser for help on using the repository browser.