LCOV - code coverage report
Current view: top level - source4/kdc - sdb_to_kdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 93 139 66.9 %
Date: 2024-04-21 15:09:00 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Database Glue between Samba and the KDC
       5             : 
       6             :    Copyright (C) Guenther Deschner <gd@samba.org> 2014
       7             :    Copyright (C) Andreas Schneider <asn@samba.org> 2014
       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             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include <kdb.h>
      26             : #include "sdb.h"
      27             : #include "sdb_kdb.h"
      28             : #include "kdc/samba_kdc.h"
      29             : #include "lib/krb5_wrap/krb5_samba.h"
      30             : 
      31             : #undef DBGC_CLASS
      32             : #define DBGC_CLASS DBGC_KERBEROS
      33             : 
      34          92 : static int SDBFlags_to_kflags(const struct SDBFlags *s,
      35             :                               krb5_flags *k)
      36             : {
      37          92 :         *k = 0;
      38             : 
      39          92 :         if (s->initial) {
      40           0 :                 *k |= KRB5_KDB_DISALLOW_TGT_BASED;
      41             :         }
      42             :         /* The forwardable and proxiable flags are set according to client and
      43             :          * server attributes. */
      44          92 :         if (!s->forwardable) {
      45           0 :                 *k |= KRB5_KDB_DISALLOW_FORWARDABLE;
      46             :         }
      47          92 :         if (!s->proxiable) {
      48           0 :                 *k |= KRB5_KDB_DISALLOW_PROXIABLE;
      49             :         }
      50          92 :         if (s->renewable) {
      51             :                 ;
      52             :         }
      53          92 :         if (s->postdate) {
      54             :                 ;
      55             :         }
      56          92 :         if (s->server) {
      57             :                 ;
      58             :         }
      59          92 :         if (s->client) {
      60             :                 ;
      61             :         }
      62          92 :         if (s->invalid) {
      63           0 :                 *k |= KRB5_KDB_DISALLOW_ALL_TIX;
      64             :         }
      65          92 :         if (s->require_preauth) {
      66          92 :                 *k |= KRB5_KDB_REQUIRES_PRE_AUTH;
      67             :         }
      68          92 :         if (s->change_pw) {
      69          92 :                 *k |= KRB5_KDB_PWCHANGE_SERVICE;
      70             :         }
      71             : #if 0
      72             :         /*
      73             :          * Do not set KRB5_KDB_REQUIRES_HW_AUTH as this would tell the client
      74             :          * to enforce hardware authentication. It prevents the use of files
      75             :          * based public key authentication which we use for testing.
      76             :          */
      77             :         if (s->require_hwauth) {
      78             :                 *k |= KRB5_KDB_REQUIRES_HW_AUTH;
      79             :         }
      80             : #endif
      81          92 :         if (s->ok_as_delegate) {
      82          92 :                 *k |= KRB5_KDB_OK_AS_DELEGATE;
      83             :         }
      84          92 :         if (s->user_to_user) {
      85             :                 ;
      86             :         }
      87          92 :         if (s->immutable) {
      88             :                 ;
      89             :         }
      90          92 :         if (s->trusted_for_delegation) {
      91           0 :                 *k |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
      92             :         }
      93          92 :         if (s->allow_kerberos4) {
      94             :                 ;
      95             :         }
      96          92 :         if (s->allow_digest) {
      97             :                 ;
      98             :         }
      99          92 :         if (s->no_auth_data_reqd) {
     100           0 :                 *k |= KRB5_KDB_NO_AUTH_DATA_REQUIRED;
     101             :         }
     102             : 
     103          92 :         return 0;
     104             : }
     105             : 
     106          92 : static int sdb_event_to_kmod(krb5_context context,
     107             :                              const struct sdb_event *s,
     108             :                              krb5_db_entry *k)
     109             : {
     110             :         krb5_error_code ret;
     111          92 :         krb5_principal principal = NULL;
     112             : 
     113          92 :         if (s->principal != NULL) {
     114          92 :                 ret = krb5_copy_principal(context,
     115          92 :                                           s->principal,
     116             :                                           &principal);
     117          92 :                 if (ret != 0) {
     118           0 :                         return ret;
     119             :                 }
     120             :         }
     121             : 
     122          92 :         ret = krb5_dbe_update_mod_princ_data(context,
     123          92 :                                              k, s->time,
     124             :                                              principal);
     125             : 
     126          92 :         krb5_free_principal(context, principal);
     127             : 
     128          92 :         return ret;
     129             : }
     130             : 
     131             : /* sets up salt on the 2nd array position */
     132             : 
     133         176 : static int sdb_salt_to_krb5_key_data(const struct sdb_salt *s,
     134             :                                      krb5_key_data *k)
     135             : {
     136         176 :         switch (s->type) {
     137             : #if 0
     138             :         /* for now use the special mechanism where the MIT KDC creates the salt
     139             :          * on its own */
     140             :         case 3: /* FIXME KRB5_PW_SALT */
     141             :                 k->key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL;
     142             :                 break;
     143             :         /*
     144             :         case hdb_afs3_salt:
     145             :                 k->key_data_type[1] = KRB5_KDB_SALTTYPE_AFS3;
     146             :                 break;
     147             :         */
     148             : #endif
     149             :         default:
     150         176 :                 k->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
     151         176 :                 break;
     152             :         }
     153             : 
     154         176 :         k->key_data_contents[1] = malloc(s->salt.length);
     155         176 :         if (k->key_data_contents[1] == NULL) {
     156           0 :                 return ENOMEM;
     157             :         }
     158         176 :         memcpy(k->key_data_contents[1],
     159         176 :                s->salt.data,
     160         176 :                s->salt.length);
     161         176 :         k->key_data_length[1] = s->salt.length;
     162             : 
     163         176 :         return 0;
     164             : }
     165             : 
     166         268 : static int sdb_key_to_krb5_key_data(const struct sdb_key *s,
     167             :                                     int kvno,
     168             :                                     krb5_key_data *k)
     169             : {
     170         268 :         int ret = 0;
     171             : 
     172         268 :         ZERO_STRUCTP(k);
     173             : 
     174         268 :         k->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
     175         268 :         k->key_data_kvno = kvno;
     176             : 
     177         268 :         k->key_data_type[0] = KRB5_KEY_TYPE(&s->key);
     178         268 :         k->key_data_length[0] = KRB5_KEY_LENGTH(&s->key);
     179         268 :         k->key_data_contents[0] = malloc(k->key_data_length[0]);
     180         268 :         if (k->key_data_contents[0] == NULL) {
     181           0 :                 return ENOMEM;
     182             :         }
     183             : 
     184         268 :         memcpy(k->key_data_contents[0],
     185         268 :                KRB5_KEY_DATA(&s->key),
     186         268 :                k->key_data_length[0]);
     187             : 
     188         268 :         if (s->salt != NULL) {
     189         176 :                 ret = sdb_salt_to_krb5_key_data(s->salt, k);
     190         176 :                 if (ret) {
     191           0 :                         memset(k->key_data_contents[0], 0, k->key_data_length[0]);
     192           0 :                         free(k->key_data_contents[0]);
     193             :                 }
     194             :         }
     195             : 
     196         268 :         return ret;
     197             : }
     198             : 
     199           0 : static void free_krb5_db_entry(krb5_context context,
     200             :                                krb5_db_entry *k)
     201             : {
     202           0 :         krb5_tl_data *tl_data_next = NULL;
     203           0 :         krb5_tl_data *tl_data = NULL;
     204             :         int i, j;
     205             : 
     206           0 :         if (k == NULL) {
     207           0 :                 return;
     208             :         }
     209             : 
     210           0 :         krb5_free_principal(context, k->princ);
     211             : 
     212           0 :         for (tl_data = k->tl_data; tl_data; tl_data = tl_data_next) {
     213           0 :                 tl_data_next = tl_data->tl_data_next;
     214           0 :                 if (tl_data->tl_data_contents != NULL) {
     215           0 :                         free(tl_data->tl_data_contents);
     216             :                 }
     217           0 :                 free(tl_data);
     218             :         }
     219             : 
     220           0 :         if (k->key_data != NULL) {
     221           0 :                 for (i = 0; i < k->n_key_data; i++) {
     222           0 :                         for (j = 0; j < k->key_data[i].key_data_ver; j++) {
     223           0 :                                 if (k->key_data[i].key_data_length[j] != 0) {
     224           0 :                                         if (k->key_data[i].key_data_contents[j] != NULL) {
     225           0 :                                                 BURN_PTR_SIZE(k->key_data[i].key_data_contents[j], k->key_data[i].key_data_length[j]);
     226           0 :                                                 free(k->key_data[i].key_data_contents[j]);
     227             :                                         }
     228             :                                 }
     229           0 :                                 k->key_data[i].key_data_contents[j] = NULL;
     230           0 :                                 k->key_data[i].key_data_length[j] = 0;
     231           0 :                                 k->key_data[i].key_data_type[j] = 0;
     232             :                         }
     233             :                 }
     234           0 :                 free(k->key_data);
     235             :         }
     236             : 
     237           0 :         ZERO_STRUCTP(k);
     238             : }
     239             : 
     240          92 : int sdb_entry_to_krb5_db_entry(krb5_context context,
     241             :                                const struct sdb_entry *s,
     242             :                                krb5_db_entry *k)
     243             : {
     244          92 :         struct samba_kdc_entry *ske = s->skdc_entry;
     245             :         krb5_error_code ret;
     246             :         int i;
     247             : 
     248          92 :         ZERO_STRUCTP(k);
     249             : 
     250          92 :         k->magic = KRB5_KDB_MAGIC_NUMBER;
     251          92 :         k->len = KRB5_KDB_V1_BASE_LENGTH;
     252             : 
     253          92 :         ret = krb5_copy_principal(context,
     254          92 :                                   s->principal,
     255             :                                   &k->princ);
     256          92 :         if (ret) {
     257           0 :                 free_krb5_db_entry(context, k);
     258           0 :                 return ret;
     259             :         }
     260             : 
     261          92 :         ret = SDBFlags_to_kflags(&s->flags,
     262             :                                  &k->attributes);
     263          92 :         if (ret) {
     264           0 :                 free_krb5_db_entry(context, k);
     265           0 :                 return ret;
     266             :         }
     267             : 
     268          92 :         if (s->max_life != NULL) {
     269          92 :                 k->max_life = *s->max_life;
     270             :         }
     271          92 :         if (s->max_renew != NULL) {
     272          92 :                 k->max_renewable_life = *s->max_renew;
     273             :         }
     274          92 :         if (s->valid_end != NULL) {
     275           0 :                 k->expiration = *s->valid_end;
     276             :         }
     277          92 :         if (s->pw_end != NULL) {
     278           0 :                 k->pw_expiration = *s->pw_end;
     279             :         }
     280             : 
     281             :         /* last_success */
     282             :         /* last_failed */
     283             :         /* fail_auth_count */
     284             :         /* n_tl_data */
     285             : 
     286             :         /*
     287             :          * If we leave early when looking up the realm, we do not have all
     288             :          * information about a principal. We need to construct a db entry
     289             :          * with minimal information, so skip this part.
     290             :          */
     291          92 :         if (s->created_by.time != 0) {
     292          92 :                 ret = sdb_event_to_kmod(context,
     293          92 :                                         s->modified_by ? s->modified_by : &s->created_by,
     294             :                                         k);
     295          92 :                 if (ret) {
     296           0 :                         free_krb5_db_entry(context, k);
     297           0 :                         return ret;
     298             :                 }
     299             :         }
     300             : 
     301             :         /* FIXME: TODO HDB Extensions */
     302             : 
     303             :         /*
     304             :          * Don't copy keys (allow password auth) if s->flags.require_hwauth is
     305             :          * set which translates to UF_SMARTCARD_REQUIRED.
     306             :          */
     307          92 :         if (s->keys.len > 0 && s->flags.require_hwauth == 0) {
     308          92 :                 k->key_data = malloc(s->keys.len * sizeof(krb5_key_data));
     309          92 :                 if (k->key_data == NULL) {
     310           0 :                         free_krb5_db_entry(context, k);
     311           0 :                         return ret;
     312             :                 }
     313             : 
     314         360 :                 for (i=0; i < s->keys.len; i++) {
     315         268 :                         ret = sdb_key_to_krb5_key_data(&s->keys.val[i],
     316         268 :                                                        s->kvno,
     317         268 :                                                        &k->key_data[i]);
     318         268 :                         if (ret) {
     319           0 :                                 free_krb5_db_entry(context, k);
     320           0 :                                 return ret;
     321             :                         }
     322             : 
     323         268 :                         k->n_key_data++;
     324             :                 }
     325             :         }
     326             : 
     327          92 :         k->e_data = (void *)ske;
     328          92 :         if (ske != NULL) {
     329          92 :                 ske->kdc_entry = k;
     330             :         }
     331          92 :         return 0;
     332             : }

Generated by: LCOV version 1.14