source: branches/samba-3.5.x/libcli/auth/schannel_state_tdb.c

Last change on this file was 734, checked in by Silvan Scherrer, 13 years ago

Samba Server 3.5: update branche to 3.5.14

File size: 6.3 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 "../libcli/auth/libcli_auth.h"
26#include "../libcli/auth/schannel_state.h"
27#include "../librpc/gen_ndr/ndr_schannel.h"
28
29/********************************************************************
30 ********************************************************************/
31
32NTSTATUS schannel_store_session_key_tdb(struct tdb_context *tdb,
33 TALLOC_CTX *mem_ctx,
34 struct netlogon_creds_CredentialState *creds)
35{
36 enum ndr_err_code ndr_err;
37 DATA_BLOB blob;
38 TDB_DATA value;
39 int ret;
40 char *keystr;
41
42 keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
43 SECRETS_SCHANNEL_STATE,
44 creds->computer_name);
45 if (!keystr) {
46 return NT_STATUS_NO_MEMORY;
47 }
48
49 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, creds,
50 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
51 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
52 talloc_free(keystr);
53 return ndr_map_error2ntstatus(ndr_err);
54 }
55
56 value.dptr = blob.data;
57 value.dsize = blob.length;
58
59 ret = tdb_store_bystring(tdb, keystr, value, TDB_REPLACE);
60 if (ret != TDB_SUCCESS) {
61 DEBUG(0,("Unable to add %s to session key db - %s\n",
62 keystr, tdb_errorstr(tdb)));
63 talloc_free(keystr);
64 return NT_STATUS_INTERNAL_DB_CORRUPTION;
65 }
66
67 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
68 keystr));
69
70 if (DEBUGLEVEL >= 10) {
71 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
72 }
73
74 talloc_free(keystr);
75
76 return NT_STATUS_OK;
77}
78
79/********************************************************************
80 ********************************************************************/
81
82NTSTATUS schannel_fetch_session_key_tdb(struct tdb_context *tdb,
83 TALLOC_CTX *mem_ctx,
84 const char *computer_name,
85 struct netlogon_creds_CredentialState **pcreds)
86{
87 NTSTATUS status;
88 TDB_DATA value;
89 enum ndr_err_code ndr_err;
90 DATA_BLOB blob;
91 struct netlogon_creds_CredentialState *creds = NULL;
92 char *keystr = NULL;
93
94 *pcreds = NULL;
95
96 keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
97 SECRETS_SCHANNEL_STATE,
98 computer_name);
99 if (!keystr) {
100 status = NT_STATUS_NO_MEMORY;
101 goto done;
102 }
103
104 value = tdb_fetch_bystring(tdb, keystr);
105 if (!value.dptr) {
106 DEBUG(0,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
107 keystr ));
108 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
109 goto done;
110 }
111
112 creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
113 if (!creds) {
114 status = NT_STATUS_NO_MEMORY;
115 goto done;
116 }
117
118 blob = data_blob_const(value.dptr, value.dsize);
119
120 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, creds,
121 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
122 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
123 status = ndr_map_error2ntstatus(ndr_err);
124 goto done;
125 }
126
127 if (DEBUGLEVEL >= 10) {
128 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
129 }
130
131 DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n",
132 keystr));
133
134 status = NT_STATUS_OK;
135
136 done:
137
138 talloc_free(keystr);
139
140 if (!NT_STATUS_IS_OK(status)) {
141 talloc_free(creds);
142 return status;
143 }
144
145 *pcreds = creds;
146
147 return NT_STATUS_OK;
148}
149
150/********************************************************************
151
152 Validate an incoming authenticator against the credentials for the remote
153 machine.
154
155 The credentials are (re)read and from the schannel database, and
156 written back after the caclulations are performed.
157
158 The creds_out parameter (if not NULL) returns the credentials, if
159 the caller needs some of that information.
160
161 ********************************************************************/
162
163NTSTATUS schannel_creds_server_step_check_tdb(struct tdb_context *tdb,
164 TALLOC_CTX *mem_ctx,
165 const char *computer_name,
166 bool schannel_required_for_call,
167 bool schannel_in_use,
168 struct netr_Authenticator *received_authenticator,
169 struct netr_Authenticator *return_authenticator,
170 struct netlogon_creds_CredentialState **creds_out)
171{
172 struct netlogon_creds_CredentialState *creds = NULL;
173 NTSTATUS status;
174 int ret;
175
176 ret = tdb_transaction_start(tdb);
177 if (ret != 0) {
178 return NT_STATUS_INTERNAL_DB_CORRUPTION;
179 }
180
181 /* Because this is a shared structure (even across
182 * disconnects) we must update the database every time we
183 * update the structure */
184
185 status = schannel_fetch_session_key_tdb(tdb, mem_ctx, computer_name,
186 &creds);
187
188 /* If we are flaged that schannel is required for a call, and
189 * it is not in use, then make this an error */
190
191 /* It would be good to make this mandatory once schannel is
192 * negotiated, but this is not what windows does */
193 if (schannel_required_for_call && !schannel_in_use) {
194 DEBUG(0,("schannel_creds_server_step_check_tdb: "
195 "client %s not using schannel for netlogon, despite negotiating it\n",
196 computer_name));
197 TALLOC_FREE(creds);
198 tdb_transaction_cancel(tdb);
199 return NT_STATUS_ACCESS_DENIED;
200 }
201
202 if (NT_STATUS_IS_OK(status)) {
203 status = netlogon_creds_server_step_check(creds,
204 received_authenticator,
205 return_authenticator);
206 }
207
208 if (NT_STATUS_IS_OK(status)) {
209 status = schannel_store_session_key_tdb(tdb, mem_ctx, creds);
210 }
211
212 if (NT_STATUS_IS_OK(status)) {
213 tdb_transaction_commit(tdb);
214 if (creds_out) {
215 *creds_out = talloc_move(mem_ctx, &creds);
216 }
217 } else {
218 tdb_transaction_cancel(tdb);
219 }
220
221 TALLOC_FREE(creds);
222 return status;
223}
Note: See TracBrowser for help on using the repository browser.