~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/dsdb/samdb/samdb.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   interface functions for the sam database
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2004
 
7
   Copyright (C) Volker Lendecke 2004
 
8
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
 
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 "librpc/gen_ndr/ndr_netlogon.h"
 
26
#include "librpc/gen_ndr/ndr_misc.h"
 
27
#include "librpc/gen_ndr/ndr_security.h"
 
28
#include "lib/events/events.h"
 
29
#include "lib/ldb/include/ldb.h"
 
30
#include "lib/ldb/include/ldb_errors.h"
 
31
#include "libcli/security/security.h"
 
32
#include "libcli/auth/libcli_auth.h"
 
33
#include "libcli/ldap/ldap_ndr.h"
 
34
#include "system/time.h"
 
35
#include "system/filesys.h"
 
36
#include "ldb_wrap.h"
 
37
#include "../lib/util/util_ldb.h"
 
38
#include "dsdb/samdb/samdb.h"
 
39
#include "dsdb/common/flags.h"
 
40
#include "param/param.h"
 
41
#include "lib/events/events.h"
 
42
#include "auth/credentials/credentials.h"
 
43
#include "param/secrets.h"
 
44
 
 
45
char *samdb_relative_path(struct ldb_context *ldb,
 
46
                                 TALLOC_CTX *mem_ctx, 
 
47
                                 const char *name) 
 
48
{
 
49
        const char *base_url = 
 
50
                (const char *)ldb_get_opaque(ldb, "ldb_url");
 
51
        char *path, *p, *full_name;
 
52
        if (name == NULL) {
 
53
                return NULL;
 
54
        }
 
55
        if (name[0] == 0 || name[0] == '/' || strstr(name, ":/")) {
 
56
                return talloc_strdup(mem_ctx, name);
 
57
        }
 
58
        path = talloc_strdup(mem_ctx, base_url);
 
59
        if (path == NULL) {
 
60
                return NULL;
 
61
        }
 
62
        if ( (p = strrchr(path, '/')) != NULL) {
 
63
                p[0] = '\0';
 
64
                full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
 
65
        } else {
 
66
                full_name = talloc_asprintf(mem_ctx, "./%s", name);
 
67
        }
 
68
        talloc_free(path);
 
69
        return full_name;
 
70
}
 
71
 
 
72
struct cli_credentials *samdb_credentials(TALLOC_CTX *mem_ctx, 
 
73
                                          struct tevent_context *event_ctx, 
 
74
                                          struct loadparm_context *lp_ctx) 
 
75
{
 
76
        struct cli_credentials *cred = cli_credentials_init(mem_ctx);
 
77
        if (!cred) {
 
78
                return NULL;
 
79
        }
 
80
        cli_credentials_set_conf(cred, lp_ctx);
 
81
 
 
82
        /* We don't want to use krb5 to talk to our samdb - recursion
 
83
         * here would be bad, and this account isn't in the KDC
 
84
         * anyway */
 
85
        cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS);
 
86
 
 
87
        if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, event_ctx, lp_ctx, NULL, NULL,
 
88
                                                         SECRETS_LDAP_FILTER))) {
 
89
                /* Perfectly OK - if not against an LDAP backend */
 
90
                return NULL;
 
91
        }
 
92
        return cred;
 
93
}
 
94
 
 
95
/*
 
96
  connect to the SAM database
 
97
  return an opaque context pointer on success, or NULL on failure
 
98
 */
 
99
struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, 
 
100
                                  struct tevent_context *ev_ctx,
 
101
                                  struct loadparm_context *lp_ctx,
 
102
                                  struct auth_session_info *session_info)
 
103
{
 
104
        struct ldb_context *ldb;
 
105
        ldb = ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, 
 
106
                               lp_sam_url(lp_ctx), session_info,
 
107
                               samdb_credentials(mem_ctx, ev_ctx, lp_ctx), 
 
108
                               0, NULL);
 
109
        if (!ldb) {
 
110
                return NULL;
 
111
        }
 
112
        dsdb_make_schema_global(ldb);
 
113
        return ldb;
 
114
}
 
115
 
 
116
/*
 
117
  copy from a template record to a message
 
118
*/
 
119
int samdb_copy_template(struct ldb_context *ldb, 
 
120
                        struct ldb_message *msg, const char *name,
 
121
                        const char **errstring)
 
122
{
 
123
        struct ldb_result *res;
 
124
        struct ldb_message *t;
 
125
        int ret, i, j;
 
126
        struct ldb_context *templates_ldb;
 
127
        char *templates_ldb_path; 
 
128
        struct ldb_dn *basedn;
 
129
        struct tevent_context *event_ctx;
 
130
        struct loadparm_context *lp_ctx;
 
131
 
 
132
        templates_ldb = talloc_get_type(ldb_get_opaque(ldb, "templates_ldb"), struct ldb_context);
 
133
 
 
134
        if (!templates_ldb) {
 
135
                templates_ldb_path = samdb_relative_path(ldb, 
 
136
                                                         msg, 
 
137
                                                         "templates.ldb");
 
138
                if (!templates_ldb_path) {
 
139
                        *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct path for template db");
 
140
                        return LDB_ERR_OPERATIONS_ERROR;
 
141
                }
 
142
                
 
143
                event_ctx = ldb_get_event_context(ldb);
 
144
                lp_ctx = (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
 
145
 
 
146
                /* FIXME: need to remove this wehn we finally pass the event
 
147
                 * context around in ldb */
 
148
                if (event_ctx == NULL) {
 
149
                        event_ctx = s4_event_context_init(templates_ldb);
 
150
                }
 
151
 
 
152
                templates_ldb = ldb_wrap_connect(ldb, event_ctx, lp_ctx, 
 
153
                                                templates_ldb_path, NULL,
 
154
                                                NULL, 0, NULL);
 
155
                talloc_free(templates_ldb_path);
 
156
                if (!templates_ldb) {
 
157
                        *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to connect to templates db at: %s",
 
158
                                             templates_ldb_path);
 
159
                        return LDB_ERR_OPERATIONS_ERROR;
 
160
                }
 
161
                
 
162
                ret = ldb_set_opaque(ldb, "templates_ldb", templates_ldb);
 
163
                if (ret != LDB_SUCCESS) {
 
164
                        return ret;
 
165
                }
 
166
        }
 
167
        *errstring = NULL;      
 
168
 
 
169
        basedn = ldb_dn_new(templates_ldb, ldb, "cn=Templates");
 
170
        if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) {
 
171
                talloc_free(basedn);
 
172
                *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'", 
 
173
                                             name);
 
174
                return LDB_ERR_OPERATIONS_ERROR;
 
175
        }
 
176
        
 
177
        /* pull the template record */
 
178
        ret = ldb_search(templates_ldb, msg, &res, basedn, LDB_SCOPE_BASE, NULL, "distinguishedName=*");
 
179
        talloc_free(basedn);
 
180
        if (ret != LDB_SUCCESS) {
 
181
                *errstring = talloc_steal(msg, ldb_errstring(templates_ldb));
 
182
                return ret;
 
183
        }
 
184
        if (res->count != 1) {
 
185
                *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1", 
 
186
                                             name, 
 
187
                                             res->count);
 
188
                talloc_free(res);
 
189
                return LDB_ERR_OPERATIONS_ERROR;
 
190
        }
 
191
        t = res->msgs[0];
 
192
 
 
193
        for (i = 0; i < t->num_elements; i++) {
 
194
                struct ldb_message_element *el = &t->elements[i];
 
195
                /* some elements should not be copied from the template */
 
196
                if (ldb_attr_cmp(el->name, "cn") == 0 ||
 
197
                    ldb_attr_cmp(el->name, "name") == 0 ||
 
198
                    ldb_attr_cmp(el->name, "objectClass") == 0 ||
 
199
                    ldb_attr_cmp(el->name, "sAMAccountName") == 0 ||
 
200
                    ldb_attr_cmp(el->name, "sAMAccountName") == 0 ||
 
201
                    ldb_attr_cmp(el->name, "distinguishedName") == 0 ||
 
202
                    ldb_attr_cmp(el->name, "objectGUID") == 0) {
 
203
                        continue;
 
204
                }
 
205
                for (j = 0; j < el->num_values; j++) {
 
206
                        ret = samdb_find_or_add_attribute(ldb, msg, el->name, 
 
207
                                                          (char *)el->values[j].data);
 
208
                        if (ret) {
 
209
                                *errstring = talloc_asprintf(msg, "Adding attribute %s failed.", el->name);
 
210
                                talloc_free(res);
 
211
                                return ret;
 
212
                        }
 
213
                }
 
214
        }
 
215
 
 
216
        talloc_free(res);
 
217
 
 
218
        return LDB_SUCCESS;
 
219
}
 
220
 
 
221
 
 
222
/****************************************************************************
 
223
 Create the SID list for this user.
 
224
****************************************************************************/
 
225
NTSTATUS security_token_create(TALLOC_CTX *mem_ctx, 
 
226
                               struct tevent_context *ev_ctx, 
 
227
                               struct loadparm_context *lp_ctx,
 
228
                               struct dom_sid *user_sid,
 
229
                               struct dom_sid *group_sid, 
 
230
                               int n_groupSIDs,
 
231
                               struct dom_sid **groupSIDs, 
 
232
                               bool is_authenticated,
 
233
                               struct security_token **token)
 
234
{
 
235
        struct security_token *ptoken;
 
236
        int i;
 
237
        NTSTATUS status;
 
238
 
 
239
        ptoken = security_token_initialise(mem_ctx);
 
240
        NT_STATUS_HAVE_NO_MEMORY(ptoken);
 
241
 
 
242
        ptoken->sids = talloc_array(ptoken, struct dom_sid *, n_groupSIDs + 5);
 
243
        NT_STATUS_HAVE_NO_MEMORY(ptoken->sids);
 
244
 
 
245
        ptoken->user_sid = talloc_reference(ptoken, user_sid);
 
246
        ptoken->group_sid = talloc_reference(ptoken, group_sid);
 
247
        ptoken->privilege_mask = 0;
 
248
 
 
249
        ptoken->sids[0] = ptoken->user_sid;
 
250
        ptoken->sids[1] = ptoken->group_sid;
 
251
 
 
252
        /*
 
253
         * Finally add the "standard" SIDs.
 
254
         * The only difference between guest and "anonymous"
 
255
         * is the addition of Authenticated_Users.
 
256
         */
 
257
        ptoken->sids[2] = dom_sid_parse_talloc(ptoken->sids, SID_WORLD);
 
258
        NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[2]);
 
259
        ptoken->sids[3] = dom_sid_parse_talloc(ptoken->sids, SID_NT_NETWORK);
 
260
        NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[3]);
 
261
        ptoken->num_sids = 4;
 
262
 
 
263
        if (is_authenticated) {
 
264
                ptoken->sids[4] = dom_sid_parse_talloc(ptoken->sids, SID_NT_AUTHENTICATED_USERS);
 
265
                NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[4]);
 
266
                ptoken->num_sids++;
 
267
        }
 
268
 
 
269
        for (i = 0; i < n_groupSIDs; i++) {
 
270
                size_t check_sid_idx;
 
271
                for (check_sid_idx = 1; 
 
272
                     check_sid_idx < ptoken->num_sids; 
 
273
                     check_sid_idx++) {
 
274
                        if (dom_sid_equal(ptoken->sids[check_sid_idx], groupSIDs[i])) {
 
275
                                break;
 
276
                        }
 
277
                }
 
278
 
 
279
                if (check_sid_idx == ptoken->num_sids) {
 
280
                        ptoken->sids[ptoken->num_sids++] = talloc_reference(ptoken->sids, groupSIDs[i]);
 
281
                }
 
282
        }
 
283
 
 
284
        /* setup the privilege mask for this token */
 
285
        status = samdb_privilege_setup(ev_ctx, lp_ctx, ptoken);
 
286
        if (!NT_STATUS_IS_OK(status)) {
 
287
                talloc_free(ptoken);
 
288
                return status;
 
289
        }
 
290
 
 
291
        security_token_debug(10, ptoken);
 
292
 
 
293
        *token = ptoken;
 
294
 
 
295
        return NT_STATUS_OK;
 
296
}