328124c409de620cb8a02c7c340d4ddaed7a34a0
[vlendec/samba-autobuild/.git] / source4 / kdc / mit_samba.c
1 /*
2    MIT-Samba4 library
3
4    Copyright (c) 2010, Simo Sorce <idra@samba.org>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "param/param.h"
22 #include "dsdb/samdb/samdb.h"
23 #include "auth/auth.h"
24 #include "auth/credentials/credentials.h"
25 #include "system/kerberos.h"
26 #include "hdb.h"
27 #include "mit_samba_interface.h"
28 #include "auth/kerberos/kerberos.h"
29 #include "kdc/samba_kdc.h"
30 #include "kdc/pac-glue.h"
31 #include "kdc/db-glue.h"
32
33 const int mit_samba_interface_version = MIT_SAMBA_INTERFACE_VERSION;
34
35 struct mit_samba_context {
36         struct auth_session_info *session_info;
37
38         /* for compat with hdb plugin common code */
39         krb5_context context;
40         struct samba_kdc_db_context *db_ctx;
41 };
42
43 static void mit_samba_context_free(struct mit_samba_context *ctx)
44 {
45         /* free heimdal's krb5_context */
46         if (ctx->context) {
47                 krb5_free_context(ctx->context);
48         }
49
50         /* then free everything else */
51         talloc_free(ctx);
52 }
53
54 static int mit_samba_context_init(struct mit_samba_context **_ctx)
55 {
56         struct mit_samba_context *ctx;
57         const char *s4_conf_file;
58         int ret;
59
60
61         ctx = talloc(NULL, struct mit_samba_context);
62         if (!ctx) {
63                 ret = ENOMEM;
64                 goto done;
65         }
66
67         ctx->db_ctx = talloc_zero(ctx, struct samba_kdc_db_context);
68         if (!ctx->db_ctx) {
69                 ret = ENOMEM;
70                 goto done;
71         }
72
73         ctx->db_ctx->ev_ctx = tevent_context_init(ctx);
74         if (!ctx->db_ctx->ev_ctx) {
75                 ret = ENOMEM;
76                 goto done;
77         }
78         ctx->db_ctx->lp_ctx = loadparm_init(ctx);
79         if (!ctx->db_ctx->lp_ctx) {
80                 ret = ENOMEM;
81                 goto done;
82         }
83
84         /* init s4 configuration */
85         s4_conf_file = lp_configfile(ctx->db_ctx->lp_ctx);
86         if (s4_conf_file) {
87                 lp_load(ctx->db_ctx->lp_ctx, s4_conf_file);
88         } else {
89                 lp_load_default(ctx->db_ctx->lp_ctx);
90         }
91
92         ctx->session_info = system_session(ctx->db_ctx->lp_ctx);
93         if (!ctx->session_info) {
94                 ret = EFAULT;
95                 goto done;
96         }
97
98         cli_credentials_set_kerberos_state(ctx->session_info->credentials,
99                                            CRED_DONT_USE_KERBEROS);
100
101         ctx->db_ctx->ic_ctx = lp_iconv_convenience(ctx->db_ctx->lp_ctx);
102
103         ctx->db_ctx->samdb = samdb_connect(ctx,
104                                            ctx->db_ctx->ev_ctx,
105                                            ctx->db_ctx->lp_ctx,
106                                            ctx->session_info);
107         if (!ctx->db_ctx->samdb) {
108                 ret = EFAULT;
109                 goto done;
110         }
111
112         /* init heimdal's krb_context and log facilities */
113         ret = smb_krb5_init_context_basic(ctx,
114                                           ctx->db_ctx->ev_ctx,
115                                           ctx->db_ctx->lp_ctx,
116                                           &ctx->context);
117         if (ret) {
118                 goto done;
119         }
120
121         ret = 0;
122
123 done:
124         if (ret) {
125                 mit_samba_context_free(ctx);
126         } else {
127                 *_ctx = ctx;
128         }
129         return ret;
130 }
131
132
133 static int mit_samba_get_principal(struct mit_samba_context *ctx,
134                                    char *principal_string,
135                                    unsigned int flags,
136                                    hdb_entry_ex **_hentry)
137 {
138         krb5_principal principal;
139         hdb_entry_ex *hentry;
140         int ret;
141
142         hentry = talloc(ctx, hdb_entry_ex);
143         if (!hentry) {
144                 return ENOMEM;
145         }
146
147         ret = krb5_parse_name(ctx->context, principal_string, &principal);
148         if (ret) {
149                 goto done;
150         }
151
152         ret = samba_kdc_fetch(ctx->context, ctx->db_ctx,
153                               principal, flags, hentry);
154
155         krb5_free_principal(ctx->context, principal);
156
157 done:
158         if (ret) {
159                 talloc_free(hentry);
160         } else {
161                 talloc_steal(hentry->ctx, hentry);
162                 *_hentry = hentry;
163         }
164         return ret;
165 }
166
167 static int mit_samba_get_firstkey(struct mit_samba_context *ctx,
168                                   hdb_entry_ex **_hentry)
169 {
170         hdb_entry_ex *hentry;
171         int ret;
172
173         hentry = talloc(ctx, hdb_entry_ex);
174         if (!hentry) {
175                 return ENOMEM;
176         }
177
178         ret = samba_kdc_firstkey(ctx->context, ctx->db_ctx, hentry);
179
180         if (ret) {
181                 talloc_free(hentry);
182         } else {
183                 talloc_steal(hentry->ctx, hentry);
184                 *_hentry = hentry;
185         }
186         return ret;
187 }
188
189 static int mit_samba_get_nextkey(struct mit_samba_context *ctx,
190                                  hdb_entry_ex **_hentry)
191 {
192         hdb_entry_ex *hentry;
193         int ret;
194
195         hentry = talloc(ctx, hdb_entry_ex);
196         if (!hentry) {
197                 return ENOMEM;
198         }
199
200         ret = samba_kdc_nextkey(ctx->context, ctx->db_ctx, hentry);
201
202         if (ret) {
203                 talloc_free(hentry);
204         } else {
205                 talloc_steal(hentry->ctx, hentry);
206                 *_hentry = hentry;
207         }
208         return ret;
209 }
210
211 static int mit_samba_get_pac_data(struct mit_samba_context *ctx,
212                                   hdb_entry_ex *client,
213                                   DATA_BLOB *data)
214 {
215         TALLOC_CTX *tmp_ctx;
216         DATA_BLOB *pac_blob;
217         NTSTATUS nt_status;
218
219         tmp_ctx = talloc_named(ctx, 0, "mit_samba_get_pac_data context");
220         if (!tmp_ctx) {
221                 return ENOMEM;
222         }
223
224         nt_status = samba_kdc_get_pac_blob(tmp_ctx, client, &pac_blob);
225         if (!NT_STATUS_IS_OK(nt_status)) {
226                 talloc_free(tmp_ctx);
227                 return EINVAL;
228         }
229
230         data->data = (uint8_t *)malloc(pac_blob->length);
231         if (!data->data) {
232                 talloc_free(tmp_ctx);
233                 return ENOMEM;
234         }
235         memcpy(data->data, pac_blob->data, pac_blob->length);
236         data->length = pac_blob->length;
237
238         talloc_free(tmp_ctx);
239         return 0;
240 }
241
242 static int mit_samba_update_pac_data(struct mit_samba_context *ctx,
243                                      hdb_entry_ex *client,
244                                      DATA_BLOB *pac_data,
245                                      DATA_BLOB *logon_data)
246 {
247         TALLOC_CTX *tmp_ctx;
248         DATA_BLOB *logon_blob;
249         krb5_error_code code;
250         NTSTATUS nt_status;
251         krb5_pac pac = NULL;
252         int ret;
253
254         /* The user account may be set not to want the PAC */
255         if (client && !samba_princ_needs_pac(client)) {
256                 return EINVAL;
257         }
258
259         tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac_data context");
260         if (!tmp_ctx) {
261                 return ENOMEM;
262         }
263
264         logon_blob = talloc_zero(tmp_ctx, DATA_BLOB);
265         if (!logon_blob) {
266                 ret = ENOMEM;
267                 goto done;
268         }
269
270         code = krb5_pac_parse(ctx->context,
271                               pac_data->data, pac_data->length, &pac);
272         if (code) {
273                 ret = EINVAL;
274                 goto done;
275         }
276
277         nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context,
278                                               ctx->db_ctx->ic_ctx,
279                                               &pac, logon_blob);
280         if (!NT_STATUS_IS_OK(nt_status)) {
281                 DEBUG(0, ("Building PAC failed: %s\n",
282                           nt_errstr(nt_status)));
283                 ret = EINVAL;
284                 goto done;
285         }
286
287         logon_data->data = (uint8_t *)malloc(logon_blob->length);
288         if (!logon_data->data) {
289                 ret = ENOMEM;
290                 goto done;
291         }
292         memcpy(logon_data->data, logon_blob->data, logon_blob->length);
293         logon_data->length = logon_blob->length;
294
295         ret = 0;
296
297 done:
298         if (pac) krb5_pac_free(ctx->context, pac);
299         talloc_free(tmp_ctx);
300         return ret;
301 }
302
303 static int mit_samba_check_client_access(struct mit_samba_context *ctx,
304                                          hdb_entry_ex *client,
305                                          const char *client_name,
306                                          hdb_entry_ex *server,
307                                          const char *server_name,
308                                          const char *netbios_name,
309                                          bool password_change,
310                                          DATA_BLOB *e_data)
311 {
312         struct samba_kdc_entry *kdc_entry;
313         NTSTATUS nt_status;
314
315         kdc_entry = talloc_get_type(client->ctx, struct samba_kdc_entry);
316
317         nt_status = samba_kdc_check_client_access(kdc_entry,
318                                                   client_name,
319                                                   netbios_name,
320                                                   password_change);
321
322         if (!NT_STATUS_IS_OK(nt_status)) {
323                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) {
324                         return ENOMEM;
325                 }
326
327                 samba_kdc_build_edata_reply(nt_status, e_data);
328
329                 return samba_kdc_map_policy_err(nt_status);
330         }
331
332         return 0;
333 }
334
335 static int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
336                                      hdb_entry_ex *entry,
337                                      const char *target_name,
338                                      bool is_nt_enterprise_name)
339 {
340         krb5_principal target_principal;
341         int flags = 0;
342         int ret;
343
344         if (is_nt_enterprise_name) {
345                 flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE;
346         }
347
348         ret = krb5_parse_name_flags(ctx->context, target_name,
349                                     flags, &target_principal);
350         if (ret) {
351                 return ret;
352         }
353
354         ret = samba_kdc_check_identical_client_and_server(ctx->context,
355                                                           ctx->db_ctx,
356                                                           entry,
357                                                           target_principal);
358
359         krb5_free_principal(ctx->context, target_principal);
360
361         return ret;
362 }
363
364 struct mit_samba_function_table mit_samba_function_table = {
365         mit_samba_context_init,
366         mit_samba_context_free,
367         mit_samba_get_principal,
368         mit_samba_get_firstkey,
369         mit_samba_get_nextkey,
370         mit_samba_get_pac_data,
371         mit_samba_update_pac_data,
372         mit_samba_check_client_access,
373         mit_samba_check_s4u2proxy
374 };