third_party/waf: upgrade to waf 2.0.8
[Samba.git] / source4 / kdc / mit_kdc_irpc.c
blobe0021710c9f33ed07f2f6a4c12585e1d9856d6d6
1 /*
2 * Unix SMB/CIFS implementation.
4 * Copyright (c) 2015 Andreas Schneider <asn@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/>.
20 #include "includes.h"
21 #include "system/kerberos.h"
22 #include "source4/auth/kerberos/kerberos.h"
23 #include "auth/kerberos/pac_utils.h"
25 #include "librpc/gen_ndr/irpc.h"
26 #include "lib/messaging/irpc.h"
27 #include "source4/librpc/gen_ndr/ndr_irpc.h"
28 #include "source4/librpc/gen_ndr/irpc.h"
30 #include "librpc/gen_ndr/ndr_krb5pac.h"
32 #include "source4/smbd/process_model.h"
33 #include "lib/param/param.h"
35 #include "samba_kdc.h"
36 #include "db-glue.h"
37 #include "sdb.h"
38 #include "mit_kdc_irpc.h"
40 struct mit_kdc_irpc_context {
41 struct task_server *task;
42 krb5_context krb5_context;
43 struct samba_kdc_db_context *db_ctx;
46 static NTSTATUS netr_samlogon_generic_logon(struct irpc_message *msg,
47 struct kdc_check_generic_kerberos *r)
49 struct PAC_Validate pac_validate;
50 DATA_BLOB pac_chksum;
51 struct PAC_SIGNATURE_DATA pac_kdc_sig;
52 struct mit_kdc_irpc_context *mki_ctx =
53 talloc_get_type(msg->private_data,
54 struct mit_kdc_irpc_context);
55 enum ndr_err_code ndr_err;
56 int code;
57 krb5_principal principal;
58 struct sdb_entry_ex sentry = {};
59 struct sdb_keys skeys;
60 unsigned int i;
61 const uint8_t *d = NULL;
63 /* There is no reply to this request */
64 r->out.generic_reply = data_blob(NULL, 0);
66 ndr_err =
67 ndr_pull_struct_blob(&r->in.generic_request,
68 msg,
69 &pac_validate,
70 (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
71 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
72 return NT_STATUS_INVALID_PARAMETER;
75 if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) {
77 * We don't implement any other message types - such as
78 * certificate validation - yet
80 return NT_STATUS_INVALID_PARAMETER;
83 if ((pac_validate.ChecksumAndSignature.length !=
84 (pac_validate.ChecksumLength + pac_validate.SignatureLength)) ||
85 (pac_validate.ChecksumAndSignature.length <
86 pac_validate.ChecksumLength) ||
87 (pac_validate.ChecksumAndSignature.length <
88 pac_validate.SignatureLength)) {
89 return NT_STATUS_INVALID_PARAMETER;
92 /* PAC Checksum */
93 pac_chksum = data_blob_const(pac_validate.ChecksumAndSignature.data,
94 pac_validate.ChecksumLength);
96 /* Create the krbtgt principal */
97 code = smb_krb5_make_principal(mki_ctx->krb5_context,
98 &principal,
99 lpcfg_realm(mki_ctx->task->lp_ctx),
100 "krbtgt",
101 lpcfg_realm(mki_ctx->task->lp_ctx),
102 NULL);
103 if (code != 0) {
104 DEBUG(0, ("Failed to create krbtgt@%s principal!\n",
105 lpcfg_realm(mki_ctx->task->lp_ctx)));
106 return NT_STATUS_NO_MEMORY;
109 /* Get the krbtgt from the DB */
110 code = samba_kdc_fetch(mki_ctx->krb5_context,
111 mki_ctx->db_ctx,
112 principal,
113 SDB_F_GET_KRBTGT | SDB_F_DECRYPT,
115 &sentry);
116 krb5_free_principal(mki_ctx->krb5_context, principal);
117 if (code != 0) {
118 DEBUG(0, ("Failed to fetch krbtgt@%s principal entry!\n",
119 lpcfg_realm(mki_ctx->task->lp_ctx)));
120 return NT_STATUS_LOGON_FAILURE;
123 /* PAC Signature */
124 pac_kdc_sig.type = pac_validate.SignatureType;
126 d = &pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength];
127 pac_kdc_sig.signature =
128 data_blob_const(d, pac_validate.SignatureLength);
131 * Brute force variant because MIT KRB5 doesn't provide a function like
132 * krb5_checksum_to_enctype().
134 skeys = sentry.entry.keys;
136 for (i = 0; i < skeys.len; i++) {
137 krb5_keyblock krbtgt_keyblock = skeys.val[i].key;
139 code = check_pac_checksum(pac_chksum,
140 &pac_kdc_sig,
141 mki_ctx->krb5_context,
142 &krbtgt_keyblock);
143 if (code == 0) {
144 break;
148 sdb_free_entry(&sentry);
150 if (code != 0) {
151 return NT_STATUS_LOGON_FAILURE;
154 return NT_STATUS_OK;
157 NTSTATUS samba_setup_mit_kdc_irpc(struct task_server *task)
159 struct samba_kdc_base_context base_ctx;
160 struct mit_kdc_irpc_context *mki_ctx;
161 NTSTATUS status;
162 int code;
164 mki_ctx = talloc_zero(task, struct mit_kdc_irpc_context);
165 if (mki_ctx == NULL) {
166 return NT_STATUS_NO_MEMORY;
168 mki_ctx->task = task;
170 base_ctx.ev_ctx = task->event_ctx;
171 base_ctx.lp_ctx = task->lp_ctx;
173 /* db-glue.h */
174 status = samba_kdc_setup_db_ctx(mki_ctx,
175 &base_ctx,
176 &mki_ctx->db_ctx);
177 if (!NT_STATUS_IS_OK(status)) {
178 return status;
181 code = smb_krb5_init_context_basic(mki_ctx,
182 task->lp_ctx,
183 &mki_ctx->krb5_context);
184 if (code != 0) {
185 return NT_STATUS_INTERNAL_ERROR;
188 status = IRPC_REGISTER(task->msg_ctx,
189 irpc,
190 KDC_CHECK_GENERIC_KERBEROS,
191 netr_samlogon_generic_logon,
192 mki_ctx);
193 if (!NT_STATUS_IS_OK(status)) {
194 return status;
197 irpc_add_name(task->msg_ctx, "kdc_server");
199 return status;