LCOV - code coverage report
Current view: top level - source4/kdc/mit-kdb - kdb_samba_policies.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 0 229 0.0 %
Date: 2024-02-14 10:14:15 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Samba KDB plugin for MIT Kerberos
       5             : 
       6             :    Copyright (c) 2010      Simo Sorce <idra@samba.org>.
       7             :    Copyright (c) 2014-2021 Andreas Schneider <asn@samba.org>
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "lib/replace/replace.h"
      24             : #include "lib/replace/system/kerberos.h"
      25             : #include "lib/util/data_blob.h"
      26             : #include "lib/util/debug.h"
      27             : #include "lib/util/fault.h"
      28             : #include "lib/util/memory.h"
      29             : #include "libcli/util/ntstatus.h"
      30             : #include "lib/krb5_wrap/krb5_samba.h"
      31             : 
      32             : #include <profile.h>
      33             : #include <kdb.h>
      34             : 
      35             : #include "kdc/mit_samba.h"
      36             : #include "kdb_samba.h"
      37             : 
      38             : #undef DBGC_CLASS
      39             : #define DBGC_CLASS DBGC_KERBEROS
      40             : 
      41             : /* FIXME: This is a krb5 function which is exported, but in no header */
      42             : extern krb5_error_code decode_krb5_padata_sequence(const krb5_data *output,
      43             :                                                    krb5_pa_data ***rep);
      44             : 
      45           0 : static krb5_error_code ks_get_netbios_name(krb5_address **addrs, char **name)
      46             : {
      47           0 :         char *nb_name = NULL;
      48             :         int len, i;
      49             : 
      50           0 :         for (i = 0; addrs[i]; i++) {
      51           0 :                 if (addrs[i]->addrtype != ADDRTYPE_NETBIOS) {
      52           0 :                         continue;
      53             :                 }
      54           0 :                 len = MIN(addrs[i]->length, 15);
      55           0 :                 nb_name = strndup((const char *)addrs[i]->contents, len);
      56           0 :                 if (!nb_name) {
      57           0 :                         return ENOMEM;
      58             :                 }
      59           0 :                 break;
      60             :         }
      61             : 
      62           0 :         if (nb_name) {
      63             :                 /* Strip space padding */
      64           0 :                 i = strlen(nb_name) - 1;
      65           0 :                 for (i = strlen(nb_name) - 1;
      66           0 :                      i > 0 && nb_name[i] == ' ';
      67           0 :                      i--) {
      68           0 :                         nb_name[i] = '\0';
      69             :                 }
      70             :         }
      71             : 
      72           0 :         *name = nb_name;
      73             : 
      74           0 :         return 0;
      75             : }
      76             : 
      77           0 : krb5_error_code kdb_samba_db_check_policy_as(krb5_context context,
      78             :                                              krb5_kdc_req *kdcreq,
      79             :                                              krb5_db_entry *client,
      80             :                                              krb5_db_entry *server,
      81             :                                              krb5_timestamp kdc_time,
      82             :                                              const char **status,
      83             :                                              krb5_pa_data ***e_data_out)
      84             : {
      85             :         struct mit_samba_context *mit_ctx;
      86             :         krb5_error_code code;
      87           0 :         char *client_name = NULL;
      88           0 :         char *server_name = NULL;
      89           0 :         char *netbios_name = NULL;
      90           0 :         char *realm = NULL;
      91           0 :         bool password_change = false;
      92             :         krb5_const_principal client_princ;
      93           0 :         DATA_BLOB int_data = { NULL, 0 };
      94             :         krb5_data d;
      95             :         krb5_pa_data **e_data;
      96             : 
      97           0 :         mit_ctx = ks_get_context(context);
      98           0 :         if (mit_ctx == NULL) {
      99           0 :                 return KRB5_KDB_DBNOTINITED;
     100             :         }
     101             : 
     102             :         /* Prefer canonicalised name from client entry */
     103           0 :         client_princ = client ? client->princ : kdcreq->client;
     104             : 
     105           0 :         if (client_princ == NULL || ks_is_kadmin(context, client_princ)) {
     106           0 :                 return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
     107             :         }
     108             : 
     109           0 :         if (krb5_princ_size(context, kdcreq->server) == 2 &&
     110           0 :             ks_is_kadmin_changepw(context, kdcreq->server)) {
     111           0 :                 code = krb5_get_default_realm(context, &realm);
     112           0 :                 if (code) {
     113           0 :                         goto done;
     114             :                 }
     115             : 
     116           0 :                 if (ks_data_eq_string(kdcreq->server->realm, realm)) {
     117           0 :                         password_change = true;
     118             :                 }
     119             :         }
     120             : 
     121           0 :         code = krb5_unparse_name(context, kdcreq->server, &server_name);
     122           0 :         if (code) {
     123           0 :                 goto done;
     124             :         }
     125             : 
     126           0 :         code = krb5_unparse_name(context, client_princ, &client_name);
     127           0 :         if (code) {
     128           0 :                 goto done;
     129             :         }
     130             : 
     131           0 :         if (kdcreq->addresses) {
     132           0 :                 code = ks_get_netbios_name(kdcreq->addresses, &netbios_name);
     133           0 :                 if (code) {
     134           0 :                         goto done;
     135             :                 }
     136             :         }
     137             : 
     138           0 :         code = mit_samba_check_client_access(mit_ctx,
     139             :                                              client,
     140             :                                              client_name,
     141             :                                              server,
     142             :                                              server_name,
     143             :                                              netbios_name,
     144             :                                              password_change,
     145             :                                              &int_data);
     146             : 
     147           0 :         if (int_data.length && int_data.data) {
     148             : 
     149             :                 /* make sure the mapped return code is returned - gd */
     150             :                 int code_tmp;
     151             : 
     152           0 :                 d = smb_krb5_data_from_blob(int_data);
     153             : 
     154           0 :                 code_tmp = decode_krb5_padata_sequence(&d, &e_data);
     155           0 :                 if (code_tmp == 0) {
     156           0 :                         *e_data_out = e_data;
     157             :                 }
     158             :         }
     159           0 : done:
     160           0 :         free(realm);
     161           0 :         free(server_name);
     162           0 :         free(client_name);
     163           0 :         free(netbios_name);
     164             : 
     165           0 :         return code;
     166             : }
     167             : 
     168           0 : static krb5_error_code ks_get_pac(krb5_context context,
     169             :                                   uint32_t flags,
     170             :                                   krb5_db_entry *client,
     171             :                                   krb5_db_entry *server,
     172             :                                   krb5_keyblock *client_key,
     173             :                                   krb5_pac *pac)
     174             : {
     175             :         struct mit_samba_context *mit_ctx;
     176             :         krb5_error_code code;
     177             : 
     178           0 :         mit_ctx = ks_get_context(context);
     179           0 :         if (mit_ctx == NULL) {
     180           0 :                 return KRB5_KDB_DBNOTINITED;
     181             :         }
     182             : 
     183           0 :         code = mit_samba_get_pac(mit_ctx,
     184             :                                  context,
     185             :                                  flags,
     186             :                                  client,
     187             :                                  server,
     188             :                                  client_key,
     189             :                                  pac);
     190           0 :         if (code != 0) {
     191           0 :                 return code;
     192             :         }
     193             : 
     194           0 :         return code;
     195             : }
     196             : 
     197             : #if KRB5_KDB_DAL_MAJOR_VERSION < 9
     198           0 : static krb5_error_code ks_verify_pac(krb5_context context,
     199             :                                      unsigned int flags,
     200             :                                      krb5_const_principal client_princ,
     201             :                                      krb5_db_entry *client,
     202             :                                      krb5_db_entry *server,
     203             :                                      krb5_db_entry *krbtgt,
     204             :                                      krb5_keyblock *server_key,
     205             :                                      krb5_keyblock *krbtgt_key,
     206             :                                      krb5_timestamp authtime,
     207             :                                      krb5_authdata **tgt_auth_data,
     208             :                                      krb5_pac *pac)
     209             : {
     210             :         struct mit_samba_context *mit_ctx;
     211           0 :         krb5_authdata **authdata = NULL;
     212           0 :         krb5_pac ipac = NULL;
     213           0 :         DATA_BLOB logon_data = { NULL, 0 };
     214             :         krb5_error_code code;
     215             : 
     216           0 :         mit_ctx = ks_get_context(context);
     217           0 :         if (mit_ctx == NULL) {
     218           0 :                 return KRB5_KDB_DBNOTINITED;
     219             :         }
     220             : 
     221             :         /* find the existing PAC, if present */
     222           0 :         code = krb5_find_authdata(context,
     223             :                                   tgt_auth_data,
     224             :                                   NULL,
     225             :                                   KRB5_AUTHDATA_WIN2K_PAC,
     226             :                                   &authdata);
     227           0 :         if (code != 0) {
     228           0 :                 return code;
     229             :         }
     230             : 
     231             :         /* no pac data */
     232           0 :         if (authdata == NULL) {
     233           0 :                 return 0;
     234             :         }
     235             : 
     236           0 :         SMB_ASSERT(authdata[0] != NULL);
     237             : 
     238           0 :         if (authdata[1] != NULL) {
     239           0 :                 code = KRB5KDC_ERR_BADOPTION; /* XXX */
     240           0 :                 goto done;
     241             :         }
     242             : 
     243           0 :         code = krb5_pac_parse(context,
     244           0 :                               authdata[0]->contents,
     245           0 :                               authdata[0]->length,
     246             :                               &ipac);
     247           0 :         if (code != 0) {
     248           0 :                 goto done;
     249             :         }
     250             : 
     251             :         /* TODO: verify this is correct
     252             :          *
     253             :          * In the constrained delegation case, the PAC is from a service
     254             :          * ticket rather than a TGT; we must verify the server and KDC
     255             :          * signatures to assert that the server did not forge the PAC.
     256             :          */
     257           0 :         if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
     258           0 :                 code = krb5_pac_verify(context,
     259             :                                        ipac,
     260             :                                        authtime,
     261             :                                        client_princ,
     262             :                                        server_key,
     263             :                                        krbtgt_key);
     264             :         } else {
     265           0 :                 code = krb5_pac_verify(context,
     266             :                                        ipac,
     267             :                                        authtime,
     268             :                                        client_princ,
     269             :                                        krbtgt_key,
     270             :                                        NULL);
     271             :         }
     272           0 :         if (code != 0) {
     273           0 :                 goto done;
     274             :         }
     275             : 
     276             :         /* check and update PAC */
     277           0 :         code = krb5_pac_parse(context,
     278           0 :                               authdata[0]->contents,
     279           0 :                               authdata[0]->length,
     280             :                               pac);
     281           0 :         if (code != 0) {
     282           0 :                 goto done;
     283             :         }
     284             : 
     285           0 :         code = mit_samba_reget_pac(mit_ctx,
     286             :                                    context,
     287             :                                    flags,
     288             :                                    client_princ,
     289             :                                    client,
     290             :                                    server,
     291             :                                    krbtgt,
     292             :                                    krbtgt_key,
     293             :                                    pac);
     294             : 
     295           0 : done:
     296           0 :         krb5_free_authdata(context, authdata);
     297           0 :         krb5_pac_free(context, ipac);
     298           0 :         free(logon_data.data);
     299             : 
     300           0 :         return code;
     301             : }
     302             : 
     303           0 : krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
     304             :                                             unsigned int flags,
     305             :                                             krb5_const_principal client_princ,
     306             :                                             krb5_const_principal server_princ,
     307             :                                             krb5_db_entry *client,
     308             :                                             krb5_db_entry *server,
     309             :                                             krb5_db_entry *krbtgt,
     310             :                                             krb5_db_entry *local_krbtgt,
     311             :                                             krb5_keyblock *client_key,
     312             :                                             krb5_keyblock *server_key,
     313             :                                             krb5_keyblock *krbtgt_key,
     314             :                                             krb5_keyblock *local_krbtgt_key,
     315             :                                             krb5_keyblock *session_key,
     316             :                                             krb5_timestamp authtime,
     317             :                                             krb5_authdata **tgt_auth_data,
     318             :                                             void *authdata_info,
     319             :                                             krb5_data ***auth_indicators,
     320             :                                             krb5_authdata ***signed_auth_data)
     321             : {
     322           0 :         krb5_const_principal ks_client_princ = NULL;
     323           0 :         krb5_db_entry *client_entry = NULL;
     324           0 :         krb5_authdata **pac_auth_data = NULL;
     325           0 :         krb5_authdata **authdata = NULL;
     326             :         krb5_boolean is_as_req;
     327             :         krb5_error_code code;
     328           0 :         krb5_pac pac = NULL;
     329             :         krb5_data pac_data;
     330           0 :         bool with_pac = false;
     331           0 :         bool generate_pac = false;
     332           0 :         char *client_name = NULL;
     333             : 
     334             : 
     335           0 :         krbtgt = krbtgt == NULL ? local_krbtgt : krbtgt;
     336           0 :         krbtgt_key = krbtgt_key == NULL ? local_krbtgt_key : krbtgt_key;
     337             : 
     338             :         /* FIXME: We don't support S4U yet */
     339           0 :         if (flags & KRB5_KDB_FLAGS_S4U) {
     340           0 :                 return KRB5_KDB_DBTYPE_NOSUP;
     341             :         }
     342             : 
     343           0 :         is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
     344             : 
     345             :         /*
     346             :          * When using s4u2proxy client_princ actually refers to the proxied user
     347             :          * while client->princ to the proxy service asking for the TGS on behalf
     348             :          * of the proxied user. So always use client_princ in preference.
     349             :          *
     350             :          * Note that when client principal is not NULL, client entry might be
     351             :          * NULL for cross-realm case, so we need to make sure to not
     352             :          * dereference NULL pointer here.
     353             :          */
     354           0 :         if (client_princ != NULL) {
     355           0 :                 ks_client_princ = client_princ;
     356           0 :                 if (!is_as_req) {
     357           0 :                         krb5_boolean is_equal = false;
     358             : 
     359           0 :                         if (client != NULL && client->princ != NULL) {
     360             :                                 is_equal =
     361           0 :                                         krb5_principal_compare(context,
     362             :                                                                client_princ,
     363           0 :                                                                client->princ);
     364             :                         }
     365             : 
     366             :                         /*
     367             :                          * When client principal is the same as supplied client
     368             :                          * entry, don't fetch it.
     369             :                          */
     370           0 :                         if (!is_equal) {
     371           0 :                                 code = ks_get_principal(context,
     372             :                                                         ks_client_princ,
     373             :                                                         0,
     374             :                                                         &client_entry);
     375           0 :                                 if (code != 0) {
     376           0 :                                         (void)krb5_unparse_name(context,
     377             :                                                                 ks_client_princ,
     378             :                                                                 &client_name);
     379             : 
     380           0 :                                         DBG_DEBUG("We didn't find the client "
     381             :                                                   "principal [%s] in our "
     382             :                                                   "database.\n",
     383             :                                                   client_name);
     384           0 :                                         SAFE_FREE(client_name);
     385             : 
     386             :                                         /*
     387             :                                          * If we didn't find client_princ in our
     388             :                                          * database it might be from another
     389             :                                          * realm.
     390             :                                          */
     391           0 :                                         client_entry = NULL;
     392             :                                 }
     393             :                         }
     394             :                 }
     395             :         } else {
     396           0 :                 if (client == NULL) {
     397           0 :                         *signed_auth_data = NULL;
     398           0 :                         return 0;
     399             :                 }
     400           0 :                 ks_client_princ = client->princ;
     401             :         }
     402             : 
     403           0 :         if (client_entry == NULL) {
     404           0 :                 client_entry = client;
     405             :         }
     406             : 
     407           0 :         if (is_as_req) {
     408           0 :                 with_pac = mit_samba_princ_needs_pac(client_entry);
     409             :         } else {
     410           0 :                 with_pac = mit_samba_princ_needs_pac(server);
     411             :         }
     412             : 
     413           0 :         code = krb5_unparse_name(context,
     414             :                                  client_princ,
     415             :                                  &client_name);
     416           0 :         if (code != 0) {
     417           0 :                 goto done;
     418             :         }
     419             : 
     420           0 :         if (is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC) != 0) {
     421           0 :                 generate_pac = true;
     422             :         }
     423             : 
     424           0 :         DBG_DEBUG("*** Sign data for client principal: %s [%s %s%s]\n",
     425             :                   client_name,
     426             :                   is_as_req ? "AS-REQ" : "TGS_REQ",
     427             :                   with_pac ? is_as_req ? "WITH_PAC" : "FIND_PAC" : "NO_PAC",
     428             :                   generate_pac ? " GENERATE_PAC" : "");
     429             : 
     430             :         /*
     431             :          * Generate PAC for the AS-REQ or check or generate one for the TGS if
     432             :          * needed.
     433             :          */
     434           0 :         if (with_pac && generate_pac) {
     435           0 :                 DBG_DEBUG("Generate PAC for AS-REQ [%s]\n", client_name);
     436             : 
     437           0 :                 code = krb5_pac_init(context, &pac);
     438           0 :                 if (code != 0) {
     439           0 :                         goto done;
     440             :                 }
     441             : 
     442           0 :                 code = ks_get_pac(context,
     443             :                                   flags,
     444             :                                   client_entry,
     445             :                                   server,
     446             :                                   NULL,
     447             :                                   &pac);
     448           0 :                 if (code != 0) {
     449           0 :                         goto done;
     450             :                 }
     451           0 :         } else if (with_pac && !is_as_req) {
     452             :                 /*
     453             :                  * Find the PAC in the TGS, if one exists.
     454             :                  */
     455           0 :                 code = krb5_find_authdata(context,
     456             :                                           tgt_auth_data,
     457             :                                           NULL,
     458             :                                           KRB5_AUTHDATA_WIN2K_PAC,
     459             :                                           &pac_auth_data);
     460           0 :                 if (code != 0) {
     461           0 :                         DBG_ERR("krb5_find_authdata failed: %d\n", code);
     462           0 :                         goto done;
     463             :                 }
     464           0 :                 DBG_DEBUG("Found PAC data for TGS-REQ [%s]\n", client_name);
     465             : 
     466           0 :                 if (pac_auth_data != NULL && pac_auth_data[0] != NULL) {
     467           0 :                         if (pac_auth_data[1] != NULL) {
     468           0 :                                 DBG_ERR("Invalid PAC data!\n");
     469           0 :                                 code = KRB5KDC_ERR_BADOPTION;
     470           0 :                                 goto done;
     471             :                         }
     472             : 
     473           0 :                         DBG_DEBUG("Verify PAC for TGS [%s]\n",
     474             :                                 client_name);
     475             : 
     476           0 :                         code = ks_verify_pac(context,
     477             :                                              flags,
     478             :                                              ks_client_princ,
     479             :                                              client_entry,
     480             :                                              server,
     481             :                                              krbtgt,
     482             :                                              server_key,
     483             :                                              krbtgt_key,
     484             :                                              authtime,
     485             :                                              tgt_auth_data,
     486             :                                              &pac);
     487           0 :                         if (code != 0) {
     488           0 :                                 goto done;
     489             :                         }
     490             :                 } else {
     491           0 :                         if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
     492           0 :                                 DBG_DEBUG("Generate PAC for constrained"
     493             :                                           "delegation TGS [%s]\n",
     494             :                                           client_name);
     495             : 
     496           0 :                                 code = krb5_pac_init(context, &pac);
     497           0 :                                 if (code != 0) {
     498           0 :                                         goto done;
     499             :                                 }
     500             : 
     501           0 :                                 code = ks_get_pac(context,
     502             :                                                   flags,
     503             :                                                   client_entry,
     504             :                                                   server,
     505             :                                                   NULL,
     506             :                                                   &pac);
     507           0 :                                 if (code != 0 && code != ENOENT) {
     508           0 :                                         goto done;
     509             :                                 }
     510             :                         }
     511             :                 }
     512             :         }
     513             : 
     514           0 :         if (pac == NULL) {
     515           0 :                 DBG_DEBUG("No PAC data - we're done [%s]\n", client_name);
     516           0 :                 *signed_auth_data = NULL;
     517           0 :                 code = 0;
     518           0 :                 goto done;
     519             :         }
     520             : 
     521           0 :         DBG_DEBUG("Signing PAC for %s [%s]\n",
     522             :                   is_as_req ? "AS-REQ" : "TGS-REQ",
     523             :                   client_name);
     524           0 :         code = krb5_pac_sign(context, pac, authtime, ks_client_princ,
     525             :                         server_key, krbtgt_key, &pac_data);
     526           0 :         if (code != 0) {
     527           0 :                 DBG_ERR("krb5_pac_sign failed: %d\n", code);
     528           0 :                 goto done;
     529             :         }
     530             : 
     531           0 :         authdata = calloc(2, sizeof(krb5_authdata *));
     532           0 :         if (authdata == NULL) {
     533           0 :                 goto done;
     534             :         }
     535             : 
     536           0 :         authdata[0] = malloc(sizeof(krb5_authdata));
     537           0 :         if (authdata[0] == NULL) {
     538           0 :                 goto done;
     539             :         }
     540             : 
     541             :         /* put in signed data */
     542           0 :         authdata[0]->magic = KV5M_AUTHDATA;
     543           0 :         authdata[0]->ad_type = KRB5_AUTHDATA_WIN2K_PAC;
     544           0 :         authdata[0]->contents = (krb5_octet *)pac_data.data;
     545           0 :         authdata[0]->length = pac_data.length;
     546             : 
     547           0 :         code = krb5_encode_authdata_container(context,
     548             :                                               KRB5_AUTHDATA_IF_RELEVANT,
     549             :                                               authdata,
     550             :                                               signed_auth_data);
     551           0 :         if (code != 0) {
     552           0 :                 goto done;
     553             :         }
     554             : 
     555           0 :         code = 0;
     556             : 
     557           0 : done:
     558           0 :         if (client_entry != NULL && client_entry != client) {
     559           0 :                 ks_free_principal(context, client_entry);
     560             :         }
     561           0 :         SAFE_FREE(client_name);
     562           0 :         krb5_free_authdata(context, authdata);
     563           0 :         krb5_pac_free(context, pac);
     564             : 
     565           0 :         return code;
     566             : }
     567             : #else /* KRB5_KDB_DAL_MAJOR_VERSION >= 9 */
     568             : static krb5_error_code ks_update_pac(krb5_context context,
     569             :                                      int flags,
     570             :                                      krb5_db_entry *client,
     571             :                                      krb5_db_entry *server,
     572             :                                      krb5_db_entry *signing_krbtgt,
     573             :                                      krb5_pac old_pac,
     574             :                                      krb5_pac new_pac)
     575             : {
     576             :         struct mit_samba_context *mit_ctx = NULL;
     577             :         krb5_error_code code;
     578             : 
     579             :         mit_ctx = ks_get_context(context);
     580             :         if (mit_ctx == NULL) {
     581             :                 return KRB5_KDB_DBNOTINITED;
     582             :         }
     583             : 
     584             :         code = mit_samba_update_pac(mit_ctx,
     585             :                                     context,
     586             :                                     flags,
     587             :                                     client,
     588             :                                     server,
     589             :                                     signing_krbtgt,
     590             :                                     old_pac,
     591             :                                     new_pac);
     592             :         if (code != 0) {
     593             :                 return code;
     594             :         }
     595             : 
     596             :         return code;
     597             : }
     598             : 
     599             : krb5_error_code kdb_samba_db_issue_pac(krb5_context context,
     600             :                                        unsigned int flags,
     601             :                                        krb5_db_entry *client,
     602             :                                        krb5_keyblock *replaced_reply_key,
     603             :                                        krb5_db_entry *server,
     604             :                                        krb5_db_entry *signing_krbtgt,
     605             :                                        krb5_timestamp authtime,
     606             :                                        krb5_pac old_pac,
     607             :                                        krb5_pac new_pac,
     608             :                                        krb5_data ***auth_indicators)
     609             : {
     610             :         char *client_name = NULL;
     611             :         char *server_name = NULL;
     612             :         krb5_error_code code = EINVAL;
     613             : 
     614             :         /* The KDC handles both signing and verification for us. */
     615             : 
     616             :         if (client != NULL) {
     617             :                 code = krb5_unparse_name(context,
     618             :                                          client->princ,
     619             :                                          &client_name);
     620             :                 if (code != 0) {
     621             :                         return code;
     622             :                 }
     623             :         }
     624             : 
     625             :         if (server != NULL) {
     626             :                 code = krb5_unparse_name(context,
     627             :                                          server->princ,
     628             :                                          &server_name);
     629             :                 if (code != 0) {
     630             :                         SAFE_FREE(client_name);
     631             :                         return code;
     632             :                 }
     633             :         }
     634             : 
     635             :         /*
     636             :          * Get a new PAC for AS-REQ or S4U2Self for our realm.
     637             :          *
     638             :          * For a simple cross-realm S4U2Proxy there will be the following TGS
     639             :          * requests after the client realm is identified:
     640             :          *
     641             :          * 1. server@SREALM to SREALM for krbtgt/CREALM@SREALM -- a regular TGS
     642             :          *    request with server's normal TGT and no S4U2Self padata.
     643             :          * 2. server@SREALM to CREALM for server@SREALM (expressed as an
     644             :          *    enterprise principal), with the TGT from #1 as header ticket and
     645             :          *    S4U2Self padata identifying the client.
     646             :          * 3. server@SREALM to SREALM for server@SREALM with S4U2Self padata,
     647             :          *    with the referral TGT from #2 as header ticket
     648             :          *
     649             :          * In request 2 the PROTOCOL_TRANSITION and CROSS_REALM flags are set,
     650             :          * and the request is for a local client (so client != NULL) and we
     651             :          * want to make a new PAC.
     652             :          *
     653             :          * In request 3 the PROTOCOL_TRANSITION and CROSS_REALM flags are also
     654             :          * set, but the request is for a non-local client (so client == NULL)
     655             :          * and we want to copy the subject PAC contained in the referral TGT.
     656             :          */
     657             :         if (old_pac == NULL ||
     658             :             (client != NULL && (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION))) {
     659             :                 DBG_NOTICE("Generate PAC for AS-REQ [client=%s, flags=%#08x]\n",
     660             :                            client_name != NULL ? client_name : "<unknown>",
     661             :                            flags);
     662             : 
     663             :                 code = ks_get_pac(context,
     664             :                                   flags,
     665             :                                   client,
     666             :                                   server,
     667             :                                   replaced_reply_key,
     668             :                                   &new_pac);
     669             :         } else {
     670             :                 DBG_NOTICE("Update PAC for TGS-REQ [client=%s, server=%s, "
     671             :                            "flags=%#08x]\n",
     672             :                            client_name != NULL ? client_name : "<unknown>",
     673             :                            server_name != NULL ? server_name : "<unknown>",
     674             :                            flags);
     675             : 
     676             :                 code = ks_update_pac(context,
     677             :                                 flags,
     678             :                                 client,
     679             :                                 server,
     680             :                                 signing_krbtgt,
     681             :                                 old_pac,
     682             :                                 new_pac);
     683             :         }
     684             :         SAFE_FREE(client_name);
     685             :         SAFE_FREE(server_name);
     686             : 
     687             :         return code;
     688             : }
     689             : #endif /* KRB5_KDB_DAL_MAJOR_VERSION */
     690             : 
     691           0 : krb5_error_code kdb_samba_db_check_allowed_to_delegate(krb5_context context,
     692             :                                                        krb5_const_principal client,
     693             :                                                        const krb5_db_entry *server,
     694             :                                                        krb5_const_principal proxy)
     695             : {
     696           0 :         struct mit_samba_context *mit_ctx = NULL;
     697             : 
     698           0 :         mit_ctx = ks_get_context(context);
     699           0 :         if (mit_ctx == NULL) {
     700           0 :                 return KRB5_KDB_DBNOTINITED;
     701             :         }
     702             : 
     703           0 :         return mit_samba_check_s4u2proxy(mit_ctx,
     704             :                                          server,
     705             :                                          proxy);
     706             : 
     707             : }
     708             : 
     709             : 
     710             : #if KRB5_KDB_DAL_MAJOR_VERSION >= 9
     711             : krb5_error_code kdb_samba_db_allowed_to_delegate_from(
     712             :                 krb5_context context,
     713             :                 krb5_const_principal client_principal,
     714             :                 krb5_const_principal server_principal,
     715             :                 krb5_pac header_pac,
     716             :                 const krb5_db_entry *proxy)
     717             : {
     718             :         struct mit_samba_context *mit_ctx = NULL;
     719             :         krb5_error_code code;
     720             : 
     721             :         mit_ctx = ks_get_context(context);
     722             :         if (mit_ctx == NULL) {
     723             :                 return KRB5_KDB_DBNOTINITED;
     724             :         }
     725             : 
     726             :         code = mit_samba_check_allowed_to_delegate_from(mit_ctx,
     727             :                                                         client_principal,
     728             :                                                         server_principal,
     729             :                                                         header_pac,
     730             :                                                         proxy);
     731             : 
     732             :         return code;
     733             : }
     734             : #endif
     735             : 
     736             : 
     737           0 : static void samba_bad_password_count(krb5_db_entry *client,
     738             :                                      krb5_error_code error_code)
     739             : {
     740           0 :         switch (error_code) {
     741           0 :         case 0:
     742           0 :                 mit_samba_zero_bad_password_count(client);
     743           0 :                 break;
     744           0 :         case KRB5KDC_ERR_PREAUTH_FAILED:
     745             :         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
     746           0 :                 mit_samba_update_bad_password_count(client);
     747           0 :                 break;
     748             :         }
     749           0 : }
     750             : 
     751           0 : void kdb_samba_db_audit_as_req(krb5_context context,
     752             :                                krb5_kdc_req *request,
     753             :                                const krb5_address *local_addr,
     754             :                                const krb5_address *remote_addr,
     755             :                                krb5_db_entry *client,
     756             :                                krb5_db_entry *server,
     757             :                                krb5_timestamp authtime,
     758             :                                krb5_error_code error_code)
     759             : {
     760             :         /*
     761             :          * FIXME: This segfaulted with a FAST test
     762             :          * FIND_FAST: <unknown client> for <unknown server>, Unknown FAST armor type 0
     763             :          */
     764           0 :         if (client == NULL) {
     765           0 :                 return;
     766             :         }
     767             : 
     768           0 :         samba_bad_password_count(client, error_code);
     769             : 
     770             :         /* TODO: perform proper audit logging for addresses */
     771             : }

Generated by: LCOV version 1.14