LCOV - code coverage report
Current view: top level - source4/kdc - mit_kdc_irpc.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 53 63 84.1 %
Date: 2024-04-21 15:09:00 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  *
       4             :  * Copyright (c) 2015      Andreas Schneider <asn@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 "system/kerberos.h"
      22             : #include "source4/auth/kerberos/kerberos.h"
      23             : #include "auth/kerberos/pac_utils.h"
      24             : 
      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"
      29             : 
      30             : #include "librpc/gen_ndr/ndr_krb5pac.h"
      31             : 
      32             : #include "source4/samba/process_model.h"
      33             : #include "lib/param/param.h"
      34             : 
      35             : #include "samba_kdc.h"
      36             : #include "db-glue.h"
      37             : #include "sdb.h"
      38             : #include "mit_kdc_irpc.h"
      39             : 
      40             : #undef DBGC_CLASS
      41             : #define DBGC_CLASS DBGC_KERBEROS
      42             : 
      43             : struct mit_kdc_irpc_context {
      44             :         struct task_server *task;
      45             :         krb5_context krb5_context;
      46             :         struct samba_kdc_db_context *db_ctx;
      47             : };
      48             : 
      49         100 : static NTSTATUS netr_samlogon_generic_logon(struct irpc_message *msg,
      50             :                                             struct kdc_check_generic_kerberos *r)
      51             : {
      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         100 :                 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         100 :         struct sdb_entry sentry = {};
      62             :         struct sdb_keys skeys;
      63             :         unsigned int i;
      64         100 :         const uint8_t *d = NULL;
      65             : 
      66             :         /* There is no reply to this request */
      67         100 :         r->out.generic_reply = data_blob(NULL, 0);
      68             : 
      69             :         ndr_err =
      70         100 :                 ndr_pull_struct_blob(&r->in.generic_request,
      71             :                                      msg,
      72             :                                      &pac_validate,
      73             :                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
      74         100 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      75           0 :                 return NT_STATUS_INVALID_PARAMETER;
      76             :         }
      77             : 
      78         100 :         if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) {
      79             :                 /*
      80             :                  * We don't implement any other message types - such as
      81             :                  * certificate validation - yet
      82             :                  */
      83           0 :                 return NT_STATUS_INVALID_PARAMETER;
      84             :         }
      85             : 
      86         100 :         if ((pac_validate.ChecksumAndSignature.length !=
      87         100 :             (pac_validate.ChecksumLength + pac_validate.SignatureLength)) ||
      88          60 :             (pac_validate.ChecksumAndSignature.length <
      89          60 :              pac_validate.ChecksumLength) ||
      90          60 :             (pac_validate.ChecksumAndSignature.length <
      91          60 :              pac_validate.SignatureLength)) {
      92          40 :                 return NT_STATUS_INVALID_PARAMETER;
      93             :         }
      94             : 
      95             :         /* PAC Checksum */
      96          60 :         pac_chksum = data_blob_const(pac_validate.ChecksumAndSignature.data,
      97          60 :                                      pac_validate.ChecksumLength);
      98             : 
      99             :         /* Create the krbtgt principal */
     100          60 :         code = smb_krb5_make_principal(mki_ctx->krb5_context,
     101             :                                       &principal,
     102          60 :                                       lpcfg_realm(mki_ctx->task->lp_ctx),
     103             :                                       "krbtgt",
     104          60 :                                       lpcfg_realm(mki_ctx->task->lp_ctx),
     105             :                                       NULL);
     106          60 :         if (code != 0) {
     107           0 :                 DBG_ERR("Failed to create krbtgt@%s principal!\n",
     108             :                         lpcfg_realm(mki_ctx->task->lp_ctx));
     109           0 :                 return NT_STATUS_NO_MEMORY;
     110             :         }
     111             : 
     112             :         /* Get the krbtgt from the DB */
     113          60 :         code = samba_kdc_fetch(mki_ctx->krb5_context,
     114             :                                mki_ctx->db_ctx,
     115             :                                principal,
     116             :                                SDB_F_GET_KRBTGT | SDB_F_DECRYPT,
     117             :                                0,
     118             :                                &sentry);
     119          60 :         krb5_free_principal(mki_ctx->krb5_context, principal);
     120          60 :         if (code != 0) {
     121           0 :                 DBG_ERR("Failed to fetch krbtgt@%s principal entry!\n",
     122             :                         lpcfg_realm(mki_ctx->task->lp_ctx));
     123           0 :                 return NT_STATUS_LOGON_FAILURE;
     124             :         }
     125             : 
     126             :         /* PAC Signature */
     127          60 :         pac_kdc_sig.type = pac_validate.SignatureType;
     128             : 
     129          60 :         d = &pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength];
     130             :         pac_kdc_sig.signature =
     131          60 :                 data_blob_const(d, pac_validate.SignatureLength);
     132             : 
     133             :         /*
     134             :          * Brute force variant because MIT KRB5 doesn't provide a function like
     135             :          * krb5_checksum_to_enctype().
     136             :          */
     137          60 :         skeys = sentry.keys;
     138             : 
     139          60 :         code = EINVAL;
     140         148 :         for (i = 0; i < skeys.len; i++) {
     141         108 :                 krb5_keyblock krbtgt_keyblock = skeys.val[i].key;
     142             : 
     143         108 :                 code = check_pac_checksum(pac_chksum,
     144             :                                           &pac_kdc_sig,
     145             :                                           mki_ctx->krb5_context,
     146             :                                           &krbtgt_keyblock);
     147         108 :                 if (code == 0) {
     148          20 :                         break;
     149             :                 }
     150             :         }
     151             : 
     152          60 :         sdb_entry_free(&sentry);
     153             : 
     154          60 :         if (code != 0) {
     155          40 :                 return NT_STATUS_LOGON_FAILURE;
     156             :         }
     157             : 
     158          20 :         return NT_STATUS_OK;
     159             : }
     160             : 
     161          17 : NTSTATUS samba_setup_mit_kdc_irpc(struct task_server *task)
     162             : {
     163          17 :         struct samba_kdc_base_context base_ctx = {};
     164             :         struct mit_kdc_irpc_context *mki_ctx;
     165             :         NTSTATUS status;
     166             :         int code;
     167             : 
     168          17 :         mki_ctx = talloc_zero(task, struct mit_kdc_irpc_context);
     169          17 :         if (mki_ctx == NULL) {
     170           0 :                 return NT_STATUS_NO_MEMORY;
     171             :         }
     172          17 :         mki_ctx->task = task;
     173             : 
     174          17 :         base_ctx.ev_ctx = task->event_ctx;
     175          17 :         base_ctx.lp_ctx = task->lp_ctx;
     176             : 
     177             :         /* db-glue.h */
     178          17 :         status = samba_kdc_setup_db_ctx(mki_ctx,
     179             :                                         &base_ctx,
     180             :                                         &mki_ctx->db_ctx);
     181          17 :         if (!NT_STATUS_IS_OK(status)) {
     182           0 :                 return status;
     183             :         }
     184             : 
     185          17 :         code = smb_krb5_init_context_basic(mki_ctx,
     186             :                                            task->lp_ctx,
     187             :                                            &mki_ctx->krb5_context);
     188          17 :         if (code != 0) {
     189           0 :                 return NT_STATUS_INTERNAL_ERROR;
     190             :         }
     191             : 
     192          17 :         status = IRPC_REGISTER(task->msg_ctx,
     193             :                                irpc,
     194             :                                KDC_CHECK_GENERIC_KERBEROS,
     195             :                                netr_samlogon_generic_logon,
     196             :                                mki_ctx);
     197          17 :         if (!NT_STATUS_IS_OK(status)) {
     198           0 :                 return status;
     199             :         }
     200             : 
     201          17 :         irpc_add_name(task->msg_ctx, "kdc_server");
     202             : 
     203          17 :         return status;
     204             : }

Generated by: LCOV version 1.14