~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to libcli/auth/schannel_state_tdb.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
*/
23
23
 
24
24
#include "includes.h"
25
 
#include "../libcli/auth/libcli_auth.h"
26
 
#include "../libcli/auth/schannel_state.h"
 
25
#include "system/filesys.h"
 
26
#include <tdb.h>
 
27
#include "../lib/util/util_tdb.h"
 
28
#include "../libcli/auth/schannel.h"
27
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
 
 
39
struct 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
}
28
62
 
29
63
/********************************************************************
30
64
 ********************************************************************/
31
65
 
32
 
NTSTATUS schannel_store_session_key_tdb(struct tdb_context *tdb,
 
66
static
 
67
NTSTATUS schannel_store_session_key_tdb(struct tdb_wrap *tdb_sc,
33
68
                                        TALLOC_CTX *mem_ctx,
34
69
                                        struct netlogon_creds_CredentialState *creds)
35
70
{
38
73
        TDB_DATA value;
39
74
        int ret;
40
75
        char *keystr;
41
 
 
42
 
        keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
43
 
                                            SECRETS_SCHANNEL_STATE,
44
 
                                            creds->computer_name);
 
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);
45
86
        if (!keystr) {
46
87
                return NT_STATUS_NO_MEMORY;
47
88
        }
48
89
 
49
 
        ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, creds,
 
90
        ndr_err = ndr_push_struct_blob(&blob, mem_ctx, creds,
50
91
                        (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
51
92
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
52
93
                talloc_free(keystr);
56
97
        value.dptr = blob.data;
57
98
        value.dsize = blob.length;
58
99
 
59
 
        ret = tdb_store_bystring(tdb, keystr, value, TDB_REPLACE);
 
100
        ret = tdb_store_bystring(tdb_sc->tdb, keystr, value, TDB_REPLACE);
60
101
        if (ret != TDB_SUCCESS) {
61
102
                DEBUG(0,("Unable to add %s to session key db - %s\n",
62
 
                         keystr, tdb_errorstr(tdb)));
 
103
                         keystr, tdb_errorstr(tdb_sc->tdb)));
63
104
                talloc_free(keystr);
64
105
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
65
106
        }
79
120
/********************************************************************
80
121
 ********************************************************************/
81
122
 
82
 
NTSTATUS schannel_fetch_session_key_tdb(struct tdb_context *tdb,
 
123
static
 
124
NTSTATUS schannel_fetch_session_key_tdb(struct tdb_wrap *tdb_sc,
83
125
                                        TALLOC_CTX *mem_ctx,
84
126
                                        const char *computer_name,
85
127
                                        struct netlogon_creds_CredentialState **pcreds)
90
132
        DATA_BLOB blob;
91
133
        struct netlogon_creds_CredentialState *creds = NULL;
92
134
        char *keystr = NULL;
 
135
        char *name_upper;
93
136
 
94
137
        *pcreds = NULL;
95
138
 
96
 
        keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
97
 
                                            SECRETS_SCHANNEL_STATE,
98
 
                                            computer_name);
 
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);
99
147
        if (!keystr) {
100
 
                status = NT_STATUS_NO_MEMORY;
101
 
                goto done;
 
148
                return NT_STATUS_NO_MEMORY;
102
149
        }
103
150
 
104
 
        value = tdb_fetch_bystring(tdb, keystr);
 
151
        value = tdb_fetch_bystring(tdb_sc->tdb, keystr);
105
152
        if (!value.dptr) {
106
 
                DEBUG(0,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
 
153
                DEBUG(10,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
107
154
                        keystr ));
108
155
                status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
109
156
                goto done;
117
164
 
118
165
        blob = data_blob_const(value.dptr, value.dsize);
119
166
 
120
 
        ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, creds,
 
167
        ndr_err = ndr_pull_struct_blob(&blob, creds, creds,
121
168
                        (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
122
169
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
123
170
                status = ndr_map_error2ntstatus(ndr_err);
136
183
 done:
137
184
 
138
185
        talloc_free(keystr);
 
186
        SAFE_FREE(value.dptr);
139
187
 
140
188
        if (!NT_STATUS_IS_OK(status)) {
141
189
                talloc_free(creds);
147
195
        return NT_STATUS_OK;
148
196
}
149
197
 
 
198
/******************************************************************************
 
199
 Wrapper around schannel_fetch_session_key_tdb()
 
200
 Note we must be root here.
 
201
*******************************************************************************/
 
202
 
 
203
NTSTATUS 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
 
 
241
NTSTATUS 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
 
150
265
/********************************************************************
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
 
 
 
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.
161
273
 ********************************************************************/
162
274
 
163
 
NTSTATUS 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)
 
275
NTSTATUS 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)
171
281
{
 
282
        TALLOC_CTX *tmpctx;
 
283
        struct tdb_wrap *tdb_sc;
172
284
        struct netlogon_creds_CredentialState *creds;
173
285
        NTSTATUS status;
174
286
        int ret;
175
287
 
176
 
        ret = tdb_transaction_start(tdb);
 
288
        tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
 
289
        if (!tmpctx) {
 
290
                return NT_STATUS_NO_MEMORY;
 
291
        }
 
292
 
 
293
        tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
 
294
        if (!tdb_sc) {
 
295
                status = NT_STATUS_ACCESS_DENIED;
 
296
                goto done;
 
297
        }
 
298
 
 
299
        ret = tdb_transaction_start(tdb_sc->tdb);
177
300
        if (ret != 0) {
178
 
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
301
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
302
                goto done;
179
303
        }
180
304
 
181
305
        /* Because this is a shared structure (even across
182
306
         * disconnects) we must update the database every time we
183
307
         * update the structure */
184
308
 
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
 
                        creds->computer_name ));
197
 
                tdb_transaction_cancel(tdb);
198
 
                return NT_STATUS_ACCESS_DENIED;
199
 
        }
200
 
 
201
 
        if (NT_STATUS_IS_OK(status)) {
202
 
                status = netlogon_creds_server_step_check(creds,
203
 
                                                          received_authenticator,
204
 
                                                          return_authenticator);
205
 
        }
206
 
 
207
 
        if (NT_STATUS_IS_OK(status)) {
208
 
                status = schannel_store_session_key_tdb(tdb, mem_ctx, creds);
209
 
        }
210
 
 
211
 
        if (NT_STATUS_IS_OK(status)) {
212
 
                tdb_transaction_commit(tdb);
213
 
                if (creds_out) {
214
 
                        *creds_out = creds;
215
 
                        talloc_steal(mem_ctx, creds);
 
309
        status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx, 
 
310
                                                computer_name, &creds);
 
311
        if (!NT_STATUS_IS_OK(status)) {
 
312
                tdb_transaction_cancel(tdb_sc->tdb);
 
313
                goto done;
 
314
        }
 
315
 
 
316
        status = netlogon_creds_server_step_check(creds,
 
317
                                                  received_authenticator,
 
318
                                                  return_authenticator);
 
319
        if (!NT_STATUS_IS_OK(status)) {
 
320
                tdb_transaction_cancel(tdb_sc->tdb);
 
321
                goto done;
 
322
        }
 
323
 
 
324
        status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
 
325
        if (!NT_STATUS_IS_OK(status)) {
 
326
                tdb_transaction_cancel(tdb_sc->tdb);
 
327
                goto done;
 
328
        }
 
329
 
 
330
        tdb_transaction_commit(tdb_sc->tdb);
 
331
 
 
332
        if (creds_out) {
 
333
                *creds_out = talloc_steal(mem_ctx, creds);
 
334
                if (!*creds_out) {
 
335
                        status = NT_STATUS_NO_MEMORY;
 
336
                        goto done;
216
337
                }
217
 
        } else {
218
 
                tdb_transaction_cancel(tdb);
219
338
        }
220
339
 
 
340
        status = NT_STATUS_OK;
 
341
 
 
342
done:
 
343
        talloc_free(tmpctx);
221
344
        return status;
222
345
}
 
346