4 Copyright (c) 2010, Simo Sorce <idra@samba.org>
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.
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.
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/>.
21 #include "param/param.h"
22 #include "dsdb/samdb/samdb.h"
23 #include "system/kerberos.h"
25 #include "mit_samba_interface.h"
26 #include "auth/kerberos/kerberos.h"
27 #include "kdc/samba_kdc.h"
28 #include "kdc/pac-glue.h"
29 #include "kdc/db-glue.h"
31 const int mit_samba_interface_version = MIT_SAMBA_INTERFACE_VERSION;
33 struct mit_samba_context {
34 struct auth_session_info *session_info;
36 /* for compat with hdb plugin common code */
38 struct samba_kdc_db_context *db_ctx;
41 static void mit_samba_context_free(struct mit_samba_context *ctx)
43 /* free heimdal's krb5_context */
45 krb5_free_context(ctx->context);
48 /* then free everything else */
52 static int mit_samba_context_init(struct mit_samba_context **_ctx)
55 struct mit_samba_context *ctx;
56 const char *s4_conf_file;
58 struct samba_kdc_base_context base_ctx;
60 ctx = talloc(NULL, struct mit_samba_context);
66 base_ctx.ev_ctx = tevent_context_init(ctx);
67 if (!base_ctx.ev_ctx) {
71 base_ctx.lp_ctx = loadparm_init_global(false);
72 if (!base_ctx.lp_ctx) {
76 /* init s4 configuration */
77 s4_conf_file = lpcfg_configfile(base_ctx.lp_ctx);
79 lpcfg_load(base_ctx.lp_ctx, s4_conf_file);
81 lpcfg_load_default(base_ctx.lp_ctx);
84 status = samba_kdc_setup_db_ctx(ctx, &base_ctx, &ctx->db_ctx);
85 if (!NT_STATUS_IS_OK(status)) {
90 /* init heimdal's krb_context and log facilities */
91 ret = smb_krb5_init_context_basic(ctx,
102 mit_samba_context_free(ctx);
110 static int mit_samba_get_principal(struct mit_samba_context *ctx,
111 char *principal_string,
113 hdb_entry_ex **_hentry)
115 krb5_principal principal;
116 hdb_entry_ex *hentry;
119 hentry = talloc(ctx, hdb_entry_ex);
124 ret = krb5_parse_name(ctx->context, principal_string, &principal);
129 ret = samba_kdc_fetch(ctx->context, ctx->db_ctx,
130 principal, flags, 0, hentry);
132 krb5_free_principal(ctx->context, principal);
138 talloc_steal(hentry->ctx, hentry);
144 static int mit_samba_get_firstkey(struct mit_samba_context *ctx,
145 hdb_entry_ex **_hentry)
147 hdb_entry_ex *hentry;
150 hentry = talloc(ctx, hdb_entry_ex);
155 ret = samba_kdc_firstkey(ctx->context, ctx->db_ctx, hentry);
160 talloc_steal(hentry->ctx, hentry);
166 static int mit_samba_get_nextkey(struct mit_samba_context *ctx,
167 hdb_entry_ex **_hentry)
169 hdb_entry_ex *hentry;
172 hentry = talloc(ctx, hdb_entry_ex);
177 ret = samba_kdc_nextkey(ctx->context, ctx->db_ctx, hentry);
182 talloc_steal(hentry->ctx, hentry);
188 static int mit_samba_get_pac_data(struct mit_samba_context *ctx,
189 hdb_entry_ex *client,
196 tmp_ctx = talloc_named(ctx, 0, "mit_samba_get_pac_data context");
201 nt_status = samba_kdc_get_pac_blob(tmp_ctx, client, &pac_blob);
202 if (!NT_STATUS_IS_OK(nt_status)) {
203 talloc_free(tmp_ctx);
207 data->data = (uint8_t *)malloc(pac_blob->length);
209 talloc_free(tmp_ctx);
212 memcpy(data->data, pac_blob->data, pac_blob->length);
213 data->length = pac_blob->length;
215 talloc_free(tmp_ctx);
219 static int mit_samba_update_pac_data(struct mit_samba_context *ctx,
220 hdb_entry_ex *client,
222 DATA_BLOB *logon_data)
225 DATA_BLOB *logon_blob;
226 krb5_error_code code;
231 /* The user account may be set not to want the PAC */
232 if (client && !samba_princ_needs_pac(client)) {
236 tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac_data context");
241 logon_blob = talloc_zero(tmp_ctx, DATA_BLOB);
247 code = krb5_pac_parse(ctx->context,
248 pac_data->data, pac_data->length, &pac);
254 nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context,
256 if (!NT_STATUS_IS_OK(nt_status)) {
257 DEBUG(0, ("Building PAC failed: %s\n",
258 nt_errstr(nt_status)));
263 logon_data->data = (uint8_t *)malloc(logon_blob->length);
264 if (!logon_data->data) {
268 memcpy(logon_data->data, logon_blob->data, logon_blob->length);
269 logon_data->length = logon_blob->length;
274 if (pac) krb5_pac_free(ctx->context, pac);
275 talloc_free(tmp_ctx);
279 static int mit_samba_check_client_access(struct mit_samba_context *ctx,
280 hdb_entry_ex *client,
281 const char *client_name,
282 hdb_entry_ex *server,
283 const char *server_name,
284 const char *netbios_name,
285 bool password_change,
288 struct samba_kdc_entry *kdc_entry;
291 kdc_entry = talloc_get_type(client->ctx, struct samba_kdc_entry);
293 nt_status = samba_kdc_check_client_access(kdc_entry,
298 if (!NT_STATUS_IS_OK(nt_status)) {
299 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) {
303 samba_kdc_build_edata_reply(nt_status, e_data);
305 return samba_kdc_map_policy_err(nt_status);
311 static int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
313 const char *target_name,
314 bool is_nt_enterprise_name)
316 krb5_principal target_principal;
320 if (is_nt_enterprise_name) {
321 flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE;
324 ret = krb5_parse_name_flags(ctx->context, target_name,
325 flags, &target_principal);
330 ret = samba_kdc_check_identical_client_and_server(ctx->context,
335 krb5_free_principal(ctx->context, target_principal);
340 struct mit_samba_function_table mit_samba_function_table = {
341 mit_samba_context_init,
342 mit_samba_context_free,
343 mit_samba_get_principal,
344 mit_samba_get_firstkey,
345 mit_samba_get_nextkey,
346 mit_samba_get_pac_data,
347 mit_samba_update_pac_data,
348 mit_samba_check_client_access,
349 mit_samba_check_s4u2proxy