LCOV - code coverage report
Current view: top level - source4/kdc - mit_kdc_irpc.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 14 61 23.0 %
Date: 2024-06-13 04:01:37 Functions: 1 2 50.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             : struct mit_kdc_irpc_context {
      41             :         struct task_server *task;
      42             :         krb5_context krb5_context;
      43             :         struct samba_kdc_db_context *db_ctx;
      44             : };
      45             : 
      46           0 : static NTSTATUS netr_samlogon_generic_logon(struct irpc_message *msg,
      47             :                                             struct kdc_check_generic_kerberos *r)
      48             : {
      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           0 :                 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           0 :         struct sdb_entry sentry = {};
      59             :         struct sdb_keys skeys;
      60             :         unsigned int i;
      61           0 :         const uint8_t *d = NULL;
      62             : 
      63             :         /* There is no reply to this request */
      64           0 :         r->out.generic_reply = data_blob(NULL, 0);
      65             : 
      66             :         ndr_err =
      67           0 :                 ndr_pull_struct_blob(&r->in.generic_request,
      68             :                                      msg,
      69             :                                      &pac_validate,
      70             :                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
      71           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      72           0 :                 return NT_STATUS_INVALID_PARAMETER;
      73             :         }
      74             : 
      75           0 :         if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) {
      76             :                 /*
      77             :                  * We don't implement any other message types - such as
      78             :                  * certificate validation - yet
      79             :                  */
      80           0 :                 return NT_STATUS_INVALID_PARAMETER;
      81             :         }
      82             : 
      83           0 :         if ((pac_validate.ChecksumAndSignature.length !=
      84           0 :             (pac_validate.ChecksumLength + pac_validate.SignatureLength)) ||
      85           0 :             (pac_validate.ChecksumAndSignature.length <
      86           0 :              pac_validate.ChecksumLength) ||
      87           0 :             (pac_validate.ChecksumAndSignature.length <
      88           0 :              pac_validate.SignatureLength)) {
      89           0 :                 return NT_STATUS_INVALID_PARAMETER;
      90             :         }
      91             : 
      92             :         /* PAC Checksum */
      93           0 :         pac_chksum = data_blob_const(pac_validate.ChecksumAndSignature.data,
      94           0 :                                      pac_validate.ChecksumLength);
      95             : 
      96             :         /* Create the krbtgt principal */
      97           0 :         code = smb_krb5_make_principal(mki_ctx->krb5_context,
      98             :                                       &principal,
      99           0 :                                       lpcfg_realm(mki_ctx->task->lp_ctx),
     100             :                                       "krbtgt",
     101           0 :                                       lpcfg_realm(mki_ctx->task->lp_ctx),
     102             :                                       NULL);
     103           0 :         if (code != 0) {
     104           0 :                 DEBUG(0, ("Failed to create krbtgt@%s principal!\n",
     105             :                           lpcfg_realm(mki_ctx->task->lp_ctx)));
     106           0 :                 return NT_STATUS_NO_MEMORY;
     107             :         }
     108             : 
     109             :         /* Get the krbtgt from the DB */
     110           0 :         code = samba_kdc_fetch(mki_ctx->krb5_context,
     111             :                                mki_ctx->db_ctx,
     112             :                                principal,
     113             :                                SDB_F_GET_KRBTGT | SDB_F_DECRYPT,
     114             :                                0,
     115             :                                &sentry);
     116           0 :         krb5_free_principal(mki_ctx->krb5_context, principal);
     117           0 :         if (code != 0) {
     118           0 :                 DEBUG(0, ("Failed to fetch krbtgt@%s principal entry!\n",
     119             :                           lpcfg_realm(mki_ctx->task->lp_ctx)));
     120           0 :                 return NT_STATUS_LOGON_FAILURE;
     121             :         }
     122             : 
     123             :         /* PAC Signature */
     124           0 :         pac_kdc_sig.type = pac_validate.SignatureType;
     125             : 
     126           0 :         d = &pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength];
     127             :         pac_kdc_sig.signature =
     128           0 :                 data_blob_const(d, pac_validate.SignatureLength);
     129             : 
     130             :         /*
     131             :          * Brute force variant because MIT KRB5 doesn't provide a function like
     132             :          * krb5_checksum_to_enctype().
     133             :          */
     134           0 :         skeys = sentry.keys;
     135             : 
     136           0 :         for (i = 0; i < skeys.len; i++) {
     137           0 :                 krb5_keyblock krbtgt_keyblock = skeys.val[i].key;
     138             : 
     139           0 :                 code = check_pac_checksum(pac_chksum,
     140             :                                           &pac_kdc_sig,
     141             :                                           mki_ctx->krb5_context,
     142             :                                           &krbtgt_keyblock);
     143           0 :                 if (code == 0) {
     144           0 :                         break;
     145             :                 }
     146             :         }
     147             : 
     148           0 :         sdb_entry_free(&sentry);
     149             : 
     150           0 :         if (code != 0) {
     151           0 :                 return NT_STATUS_LOGON_FAILURE;
     152             :         }
     153             : 
     154           0 :         return NT_STATUS_OK;
     155             : }
     156             : 
     157          12 : NTSTATUS samba_setup_mit_kdc_irpc(struct task_server *task)
     158             : {
     159             :         struct samba_kdc_base_context base_ctx;
     160             :         struct mit_kdc_irpc_context *mki_ctx;
     161             :         NTSTATUS status;
     162             :         int code;
     163             : 
     164          12 :         mki_ctx = talloc_zero(task, struct mit_kdc_irpc_context);
     165          12 :         if (mki_ctx == NULL) {
     166           0 :                 return NT_STATUS_NO_MEMORY;
     167             :         }
     168          12 :         mki_ctx->task = task;
     169             : 
     170          12 :         base_ctx.ev_ctx = task->event_ctx;
     171          12 :         base_ctx.lp_ctx = task->lp_ctx;
     172             : 
     173             :         /* db-glue.h */
     174          12 :         status = samba_kdc_setup_db_ctx(mki_ctx,
     175             :                                         &base_ctx,
     176             :                                         &mki_ctx->db_ctx);
     177          12 :         if (!NT_STATUS_IS_OK(status)) {
     178           0 :                 return status;
     179             :         }
     180             : 
     181          12 :         code = smb_krb5_init_context_basic(mki_ctx,
     182             :                                            task->lp_ctx,
     183             :                                            &mki_ctx->krb5_context);
     184          12 :         if (code != 0) {
     185           0 :                 return NT_STATUS_INTERNAL_ERROR;
     186             :         }
     187             : 
     188          12 :         status = IRPC_REGISTER(task->msg_ctx,
     189             :                                irpc,
     190             :                                KDC_CHECK_GENERIC_KERBEROS,
     191             :                                netr_samlogon_generic_logon,
     192             :                                mki_ctx);
     193          12 :         if (!NT_STATUS_IS_OK(status)) {
     194           0 :                 return status;
     195             :         }
     196             : 
     197          12 :         irpc_add_name(task->msg_ctx, "kdc_server");
     198             : 
     199          12 :         return status;
     200             : }

Generated by: LCOV version 1.13