~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source4/auth/credentials/credentials_secrets.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:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   User credentials handling (as regards on-disk files)
 
5
 
 
6
   Copyright (C) Jelmer Vernooij 2005
 
7
   Copyright (C) Tim Potter 2001
 
8
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
 
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 "lib/events/events.h"
 
26
#include <ldb.h>
 
27
#include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
 
28
#include "param/secrets.h"
 
29
#include "system/filesys.h"
 
30
#include "auth/credentials/credentials.h"
 
31
#include "auth/credentials/credentials_krb5.h"
 
32
#include "auth/kerberos/kerberos_util.h"
 
33
#include "param/param.h"
 
34
#include "lib/events/events.h"
 
35
#include "dsdb/samdb/samdb.h"
 
36
 
 
37
/**
 
38
 * Fill in credentials for the machine trust account, from the secrets database.
 
39
 * 
 
40
 * @param cred Credentials structure to fill in
 
41
 * @retval NTSTATUS error detailing any failure
 
42
 */
 
43
_PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, 
 
44
                                              struct loadparm_context *lp_ctx,
 
45
                                              struct ldb_context *ldb,
 
46
                                              const char *base,
 
47
                                              const char *filter, 
 
48
                                              char **error_string)
 
49
{
 
50
        TALLOC_CTX *mem_ctx;
 
51
        
 
52
        int ldb_ret;
 
53
        struct ldb_message *msg;
 
54
        
 
55
        const char *machine_account;
 
56
        const char *password;
 
57
        const char *old_password;
 
58
        const char *domain;
 
59
        const char *realm;
 
60
        enum netr_SchannelType sct;
 
61
        const char *salt_principal;
 
62
        char *keytab;
 
63
        const struct ldb_val *whenChanged;
 
64
 
 
65
        /* ok, we are going to get it now, don't recurse back here */
 
66
        cred->machine_account_pending = false;
 
67
 
 
68
        /* some other parts of the system will key off this */
 
69
        cred->machine_account = true;
 
70
 
 
71
        mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");
 
72
 
 
73
        if (!ldb) {
 
74
                /* Local secrets are stored in secrets.ldb */
 
75
                ldb = secrets_db_connect(mem_ctx, lp_ctx);
 
76
                if (!ldb) {
 
77
                        /* set anonymous as the fallback, if the machine account won't work */
 
78
                        cli_credentials_set_anonymous(cred);
 
79
                        *error_string = talloc_strdup(cred, "Could not open secrets.ldb");
 
80
                        talloc_free(mem_ctx);
 
81
                        return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 
82
                }
 
83
        }
 
84
 
 
85
        ldb_ret = dsdb_search_one(ldb, mem_ctx, &msg,
 
86
                                  ldb_dn_new(mem_ctx, ldb, base),
 
87
                                  LDB_SCOPE_SUBTREE,
 
88
                                  NULL, 0, "%s", filter);
 
89
 
 
90
        if (ldb_ret != LDB_SUCCESS) {
 
91
                *error_string = talloc_asprintf(cred, "Could not find entry to match filter: '%s' base: '%s': %s: %s\n",
 
92
                                                filter, base ? base : "",
 
93
                                                ldb_strerror(ldb_ret), ldb_errstring(ldb));
 
94
                /* set anonymous as the fallback, if the machine account won't work */
 
95
                cli_credentials_set_anonymous(cred);
 
96
                talloc_free(mem_ctx);
 
97
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 
98
        }
 
99
 
 
100
        password = ldb_msg_find_attr_as_string(msg, "secret", NULL);
 
101
        old_password = ldb_msg_find_attr_as_string(msg, "priorSecret", NULL);
 
102
 
 
103
        machine_account = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
 
104
 
 
105
        if (!machine_account) {
 
106
                machine_account = ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL);
 
107
                
 
108
                if (!machine_account) {
 
109
                        const char *ldap_bind_dn = ldb_msg_find_attr_as_string(msg, "ldapBindDn", NULL);
 
110
                        if (!ldap_bind_dn) {
 
111
                                *error_string = talloc_asprintf(cred, 
 
112
                                                                "Could not find 'samAccountName', "
 
113
                                                                "'servicePrincipalName' or "
 
114
                                                                "'ldapBindDn' in secrets record: %s",
 
115
                                                                ldb_dn_get_linearized(msg->dn));
 
116
                                /* set anonymous as the fallback, if the machine account won't work */
 
117
                                cli_credentials_set_anonymous(cred);
 
118
                                talloc_free(mem_ctx);
 
119
                                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 
120
                        } else {
 
121
                                /* store bind dn in credentials */
 
122
                                cli_credentials_set_bind_dn(cred, ldap_bind_dn);
 
123
                        }
 
124
                }
 
125
        }
 
126
 
 
127
        salt_principal = ldb_msg_find_attr_as_string(msg, "saltPrincipal", NULL);
 
128
        cli_credentials_set_salt_principal(cred, salt_principal);
 
129
        
 
130
        sct = ldb_msg_find_attr_as_int(msg, "secureChannelType", 0);
 
131
        if (sct) { 
 
132
                cli_credentials_set_secure_channel_type(cred, sct);
 
133
        }
 
134
        
 
135
        if (!password) {
 
136
                const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msg, "unicodePwd");
 
137
                struct samr_Password hash;
 
138
                ZERO_STRUCT(hash);
 
139
                if (nt_password_hash) {
 
140
                        memcpy(hash.hash, nt_password_hash->data, 
 
141
                               MIN(nt_password_hash->length, sizeof(hash.hash)));
 
142
                
 
143
                        cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED);
 
144
                } else {
 
145
                        cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
 
146
                }
 
147
        } else {
 
148
                cli_credentials_set_password(cred, password, CRED_SPECIFIED);
 
149
        }
 
150
 
 
151
        
 
152
        domain = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
 
153
        if (domain) {
 
154
                cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
 
155
        }
 
156
 
 
157
        realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
 
158
        if (realm) {
 
159
                cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
 
160
        }
 
161
 
 
162
        if (machine_account) {
 
163
                cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
 
164
        }
 
165
 
 
166
        cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0));
 
167
 
 
168
        whenChanged = ldb_msg_find_ldb_val(msg, "whenChanged");
 
169
        if (whenChanged) {
 
170
                time_t lct;
 
171
                if (ldb_val_to_time(whenChanged, &lct) == LDB_SUCCESS) {
 
172
                        cli_credentials_set_password_last_changed_time(cred, lct);
 
173
                }
 
174
        }
 
175
        
 
176
        /* If there was an external keytab specified by reference in
 
177
         * the LDB, then use this.  Otherwise we will make one up
 
178
         * (chewing CPU time) from the password */
 
179
        keytab = keytab_name_from_msg(cred, ldb, msg);
 
180
        if (keytab) {
 
181
                cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED);
 
182
                talloc_free(keytab);
 
183
        }
 
184
        talloc_free(mem_ctx);
 
185
        
 
186
        return NT_STATUS_OK;
 
187
}
 
188
 
 
189
/**
 
190
 * Fill in credentials for the machine trust account, from the secrets database.
 
191
 * 
 
192
 * @param cred Credentials structure to fill in
 
193
 * @retval NTSTATUS error detailing any failure
 
194
 */
 
195
_PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred,
 
196
                                                      struct loadparm_context *lp_ctx)
 
197
{
 
198
        NTSTATUS status;
 
199
        char *filter;
 
200
        char *error_string;
 
201
        /* Bleh, nasty recursion issues: We are setting a machine
 
202
         * account here, so we don't want the 'pending' flag around
 
203
         * any more */
 
204
        cred->machine_account_pending = false;
 
205
        filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, 
 
206
                                 cli_credentials_get_domain(cred));
 
207
        status = cli_credentials_set_secrets(cred, lp_ctx, NULL,
 
208
                                             SECRETS_PRIMARY_DOMAIN_DN,
 
209
                                             filter, &error_string);
 
210
        if (!NT_STATUS_IS_OK(status)) {
 
211
                DEBUG(1, ("Could not find machine account in secrets database: %s: %s", nt_errstr(status), error_string));
 
212
                talloc_free(error_string);
 
213
        }
 
214
        return status;
 
215
}
 
216
 
 
217
/**
 
218
 * Fill in credentials for the machine trust account, from the secrets database.
 
219
 * 
 
220
 * @param cred Credentials structure to fill in
 
221
 * @retval NTSTATUS error detailing any failure
 
222
 */
 
223
NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred,
 
224
                                    struct loadparm_context *lp_ctx)
 
225
{
 
226
        NTSTATUS status;
 
227
        char *filter;
 
228
        char *error_string;
 
229
        /* Bleh, nasty recursion issues: We are setting a machine
 
230
         * account here, so we don't want the 'pending' flag around
 
231
         * any more */
 
232
        cred->machine_account_pending = false;
 
233
        filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH,
 
234
                                       cli_credentials_get_realm(cred),
 
235
                                       cli_credentials_get_domain(cred));
 
236
        status = cli_credentials_set_secrets(cred, lp_ctx, NULL,
 
237
                                             SECRETS_PRINCIPALS_DN,
 
238
                                             filter, &error_string);
 
239
        if (!NT_STATUS_IS_OK(status)) {
 
240
                DEBUG(1, ("Could not find krbtgt (master Kerberos) account in secrets database: %s: %s", nt_errstr(status), error_string));
 
241
                talloc_free(error_string);
 
242
        }
 
243
        return status;
 
244
}
 
245
 
 
246
/**
 
247
 * Fill in credentials for a particular prinicpal, from the secrets database.
 
248
 * 
 
249
 * @param cred Credentials structure to fill in
 
250
 * @retval NTSTATUS error detailing any failure
 
251
 */
 
252
_PUBLIC_ NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred,
 
253
                                              struct loadparm_context *lp_ctx,
 
254
                                              const char *serviceprincipal)
 
255
{
 
256
        NTSTATUS status;
 
257
        char *filter;
 
258
        char *error_string;
 
259
        /* Bleh, nasty recursion issues: We are setting a machine
 
260
         * account here, so we don't want the 'pending' flag around
 
261
         * any more */
 
262
        cred->machine_account_pending = false;
 
263
        filter = talloc_asprintf(cred, SECRETS_PRINCIPAL_SEARCH,
 
264
                                 cli_credentials_get_realm(cred),
 
265
                                 cli_credentials_get_domain(cred),
 
266
                                 serviceprincipal);
 
267
        status = cli_credentials_set_secrets(cred, lp_ctx, NULL,
 
268
                                             SECRETS_PRINCIPALS_DN, filter,
 
269
                                             &error_string);
 
270
        if (!NT_STATUS_IS_OK(status)) {
 
271
                DEBUG(1, ("Could not find %s principal in secrets database: %s: %s", serviceprincipal, nt_errstr(status), error_string));
 
272
        }
 
273
        return status;
 
274
}
 
275
 
 
276
/**
 
277
 * Ask that when required, the credentials system will be filled with
 
278
 * machine trust account, from the secrets database.
 
279
 * 
 
280
 * @param cred Credentials structure to fill in
 
281
 * @note This function is used to call the above function after, rather 
 
282
 *       than during, popt processing.
 
283
 *
 
284
 */
 
285
_PUBLIC_ void cli_credentials_set_machine_account_pending(struct cli_credentials *cred,
 
286
                                                 struct loadparm_context *lp_ctx)
 
287
{
 
288
        cred->machine_account_pending = true;
 
289
        cred->machine_account_pending_lp_ctx = lp_ctx;
 
290
}
 
291
 
 
292