ldb:attrib_handlers: use NUMERIC_CMP in ldb_comparison_fold
[Samba.git] / source4 / kdc / mit_kdc_irpc.c
blobd2c39412081e9b6ea728985a362a2b615c1c9d15
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/samba/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 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_KERBEROS
43 struct mit_kdc_irpc_context {
44 struct task_server *task;
45 krb5_context krb5_context;
46 struct samba_kdc_db_context *db_ctx;
49 static NTSTATUS netr_samlogon_generic_logon(struct irpc_message *msg,
50 struct kdc_check_generic_kerberos *r)
52 struct PAC_Validate pac_validate;
53 DATA_BLOB pac_chksum;
54 struct PAC_SIGNATURE_DATA pac_kdc_sig;
55 struct mit_kdc_irpc_context *mki_ctx =
56 talloc_get_type(msg->private_data,
57 struct mit_kdc_irpc_context);
58 enum ndr_err_code ndr_err;
59 int code;
60 krb5_principal principal;
61 struct sdb_entry sentry = {};
62 struct sdb_keys skeys;
63 unsigned int i;
64 const uint8_t *d = NULL;
66 /* There is no reply to this request */
67 r->out.generic_reply = data_blob(NULL, 0);
69 ndr_err =
70 ndr_pull_struct_blob(&r->in.generic_request,
71 msg,
72 &pac_validate,
73 (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
74 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
75 return NT_STATUS_INVALID_PARAMETER;
78 if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) {
80 * We don't implement any other message types - such as
81 * certificate validation - yet
83 return NT_STATUS_INVALID_PARAMETER;
86 if ((pac_validate.ChecksumAndSignature.length !=
87 (pac_validate.ChecksumLength + pac_validate.SignatureLength)) ||
88 (pac_validate.ChecksumAndSignature.length <
89 pac_validate.ChecksumLength) ||
90 (pac_validate.ChecksumAndSignature.length <
91 pac_validate.SignatureLength)) {
92 return NT_STATUS_INVALID_PARAMETER;
95 /* PAC Checksum */
96 pac_chksum = data_blob_const(pac_validate.ChecksumAndSignature.data,
97 pac_validate.ChecksumLength);
99 /* Create the krbtgt principal */
100 code = smb_krb5_make_principal(mki_ctx->krb5_context,
101 &principal,
102 lpcfg_realm(mki_ctx->task->lp_ctx),
103 "krbtgt",
104 lpcfg_realm(mki_ctx->task->lp_ctx),
105 NULL);
106 if (code != 0) {
107 DBG_ERR("Failed to create krbtgt@%s principal!\n",
108 lpcfg_realm(mki_ctx->task->lp_ctx));
109 return NT_STATUS_NO_MEMORY;
112 /* Get the krbtgt from the DB */
113 code = samba_kdc_fetch(mki_ctx->krb5_context,
114 mki_ctx->db_ctx,
115 principal,
116 SDB_F_GET_KRBTGT | SDB_F_DECRYPT,
118 &sentry);
119 krb5_free_principal(mki_ctx->krb5_context, principal);
120 if (code != 0) {
121 DBG_ERR("Failed to fetch krbtgt@%s principal entry!\n",
122 lpcfg_realm(mki_ctx->task->lp_ctx));
123 return NT_STATUS_LOGON_FAILURE;
126 /* PAC Signature */
127 pac_kdc_sig.type = pac_validate.SignatureType;
129 d = &pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength];
130 pac_kdc_sig.signature =
131 data_blob_const(d, pac_validate.SignatureLength);
134 * Brute force variant because MIT KRB5 doesn't provide a function like
135 * krb5_checksum_to_enctype().
137 skeys = sentry.keys;
139 code = EINVAL;
140 for (i = 0; i < skeys.len; i++) {
141 krb5_keyblock krbtgt_keyblock = skeys.val[i].key;
143 code = check_pac_checksum(pac_chksum,
144 &pac_kdc_sig,
145 mki_ctx->krb5_context,
146 &krbtgt_keyblock);
147 if (code == 0) {
148 break;
152 sdb_entry_free(&sentry);
154 if (code != 0) {
155 return NT_STATUS_LOGON_FAILURE;
158 return NT_STATUS_OK;
161 NTSTATUS samba_setup_mit_kdc_irpc(struct task_server *task)
163 struct samba_kdc_base_context base_ctx = {};
164 struct mit_kdc_irpc_context *mki_ctx;
165 NTSTATUS status;
166 int code;
168 mki_ctx = talloc_zero(task, struct mit_kdc_irpc_context);
169 if (mki_ctx == NULL) {
170 return NT_STATUS_NO_MEMORY;
172 mki_ctx->task = task;
174 base_ctx.ev_ctx = task->event_ctx;
175 base_ctx.lp_ctx = task->lp_ctx;
177 /* db-glue.h */
178 status = samba_kdc_setup_db_ctx(mki_ctx,
179 &base_ctx,
180 &mki_ctx->db_ctx);
181 if (!NT_STATUS_IS_OK(status)) {
182 return status;
185 code = smb_krb5_init_context_basic(mki_ctx,
186 task->lp_ctx,
187 &mki_ctx->krb5_context);
188 if (code != 0) {
189 return NT_STATUS_INTERNAL_ERROR;
192 status = IRPC_REGISTER(task->msg_ctx,
193 irpc,
194 KDC_CHECK_GENERIC_KERBEROS,
195 netr_samlogon_generic_logon,
196 mki_ctx);
197 if (!NT_STATUS_IS_OK(status)) {
198 return status;
201 irpc_add_name(task->msg_ctx, "kdc_server");
203 return status;