LCOV - code coverage report
Current view: top level - source3/libnet - libnet_keytab.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 0 198 0.0 %
Date: 2021-09-23 10:06:22 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    dump the remote SAM using rpc samsync operations
       4             : 
       5             :    Copyright (C) Guenther Deschner 2008.
       6             :    Copyright (C) Michael Adam 2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "smb_krb5.h"
      24             : #include "ads.h"
      25             : #include "secrets.h"
      26             : #include "libnet/libnet_keytab.h"
      27             : 
      28             : #ifdef HAVE_KRB5
      29             : 
      30             : /****************************************************************
      31             : ****************************************************************/
      32             : 
      33           0 : static int keytab_close(struct libnet_keytab_context *ctx)
      34             : {
      35           0 :         if (!ctx) {
      36           0 :                 return 0;
      37             :         }
      38             : 
      39           0 :         if (ctx->keytab && ctx->context) {
      40           0 :                 krb5_kt_close(ctx->context, ctx->keytab);
      41             :         }
      42             : 
      43           0 :         if (ctx->context) {
      44           0 :                 krb5_free_context(ctx->context);
      45             :         }
      46             : 
      47           0 :         if (ctx->ads) {
      48           0 :                 ads_destroy(&ctx->ads);
      49             :         }
      50             : 
      51           0 :         TALLOC_FREE(ctx);
      52             : 
      53           0 :         return 0;
      54             : }
      55             : 
      56             : /****************************************************************
      57             : ****************************************************************/
      58             : 
      59           0 : krb5_error_code libnet_keytab_init(TALLOC_CTX *mem_ctx,
      60             :                                    const char *keytab_name,
      61             :                                    struct libnet_keytab_context **ctx)
      62             : {
      63           0 :         krb5_error_code ret = 0;
      64           0 :         krb5_context context = NULL;
      65           0 :         krb5_keytab keytab = NULL;
      66           0 :         const char *keytab_string = NULL;
      67             : 
      68             :         struct libnet_keytab_context *r;
      69             : 
      70           0 :         r = talloc_zero(mem_ctx, struct libnet_keytab_context);
      71           0 :         if (!r) {
      72           0 :                 return ENOMEM;
      73             :         }
      74             : 
      75           0 :         talloc_set_destructor(r, keytab_close);
      76             : 
      77           0 :         ret = smb_krb5_init_context_common(&context);
      78           0 :         if (ret) {
      79           0 :                 DBG_ERR("kerberos init context failed (%s)\n",
      80             :                         error_message(ret));
      81           0 :                 return ret;
      82             :         }
      83             : 
      84           0 :         ret = smb_krb5_kt_open_relative(context,
      85             :                                         keytab_name,
      86             :                                         true, /* write_access */
      87             :                                         &keytab);
      88           0 :         if (ret) {
      89           0 :                 DEBUG(1,("keytab_init: smb_krb5_open_keytab failed (%s)\n",
      90             :                         error_message(ret)));
      91           0 :                 krb5_free_context(context);
      92           0 :                 return ret;
      93             :         }
      94             : 
      95           0 :         ret = smb_krb5_kt_get_name(mem_ctx, context, keytab, &keytab_string);
      96           0 :         if (ret) {
      97           0 :                 krb5_kt_close(context, keytab);
      98           0 :                 krb5_free_context(context);
      99           0 :                 return ret;
     100             :         }
     101             : 
     102           0 :         r->context = context;
     103           0 :         r->keytab = keytab;
     104           0 :         r->keytab_name = keytab_string;
     105           0 :         r->clean_old_entries = false;
     106             : 
     107           0 :         *ctx = r;
     108             : 
     109           0 :         return 0;
     110             : }
     111             : 
     112             : /****************************************************************
     113             : ****************************************************************/
     114             : 
     115             : /**
     116             :  * Remove all entries that have the given principal, kvno and enctype.
     117             :  */
     118           0 : static krb5_error_code libnet_keytab_remove_entries(krb5_context context,
     119             :                                                     krb5_keytab keytab,
     120             :                                                     const char *principal,
     121             :                                                     int kvno,
     122             :                                                     const krb5_enctype enctype,
     123             :                                                     bool ignore_kvno)
     124             : {
     125             :         krb5_error_code ret;
     126             :         krb5_kt_cursor cursor;
     127             :         krb5_keytab_entry kt_entry;
     128             : 
     129           0 :         ZERO_STRUCT(kt_entry);
     130           0 :         ZERO_STRUCT(cursor);
     131             : 
     132           0 :         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
     133           0 :         if (ret) {
     134           0 :                 return 0;
     135             :         }
     136             : 
     137           0 :         while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0)
     138             :         {
     139             :                 krb5_keyblock *keyp;
     140           0 :                 char *princ_s = NULL;
     141             : 
     142           0 :                 if (kt_entry.vno != kvno && !ignore_kvno) {
     143           0 :                         goto cont;
     144             :                 }
     145             : 
     146           0 :                 keyp = KRB5_KT_KEY(&kt_entry);
     147             : 
     148           0 :                 if (KRB5_KEY_TYPE(keyp) != enctype) {
     149           0 :                         goto cont;
     150             :                 }
     151             : 
     152           0 :                 ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal,
     153             :                                             &princ_s);
     154           0 :                 if (ret) {
     155           0 :                         DEBUG(5, ("smb_krb5_unparse_name failed (%s)\n",
     156             :                                   error_message(ret)));
     157           0 :                         goto cont;
     158             :                 }
     159             : 
     160           0 :                 if (strcmp(principal, princ_s) != 0) {
     161           0 :                         goto cont;
     162             :                 }
     163             : 
     164             :                 /* match found - remove */
     165             : 
     166           0 :                 DEBUG(10, ("found entry for principal %s, kvno %d, "
     167             :                            "enctype %d - trying to remove it\n",
     168             :                            princ_s, kt_entry.vno, KRB5_KEY_TYPE(keyp)));
     169             : 
     170           0 :                 ret = krb5_kt_end_seq_get(context, keytab, &cursor);
     171           0 :                 ZERO_STRUCT(cursor);
     172           0 :                 if (ret) {
     173           0 :                         DEBUG(5, ("krb5_kt_end_seq_get failed (%s)\n",
     174             :                                   error_message(ret)));
     175           0 :                         goto cont;
     176             :                 }
     177             : 
     178           0 :                 ret = krb5_kt_remove_entry(context, keytab,
     179             :                                            &kt_entry);
     180           0 :                 if (ret) {
     181           0 :                         DEBUG(5, ("krb5_kt_remove_entry failed (%s)\n",
     182             :                                   error_message(ret)));
     183           0 :                         goto cont;
     184             :                 }
     185           0 :                 DEBUG(10, ("removed entry for principal %s, kvno %d, "
     186             :                            "enctype %d\n", princ_s, kt_entry.vno,
     187             :                            KRB5_KEY_TYPE(keyp)));
     188             : 
     189           0 :                 ret = krb5_kt_start_seq_get(context, keytab, &cursor);
     190           0 :                 if (ret) {
     191           0 :                         DEBUG(5, ("krb5_kt_start_seq_get failed (%s)\n",
     192             :                                   error_message(ret)));
     193           0 :                         goto cont;
     194             :                 }
     195             : 
     196           0 : cont:
     197           0 :                 smb_krb5_kt_free_entry(context, &kt_entry);
     198           0 :                 TALLOC_FREE(princ_s);
     199             :         }
     200             : 
     201           0 :         ret = krb5_kt_end_seq_get(context, keytab, &cursor);
     202           0 :         if (ret) {
     203           0 :                 DEBUG(5, ("krb5_kt_end_seq_get failed (%s)\n",
     204             :                           error_message(ret)));
     205             :         }
     206             : 
     207           0 :         return ret;
     208             : }
     209             : 
     210           0 : static krb5_error_code libnet_keytab_add_entry(krb5_context context,
     211             :                                                krb5_keytab keytab,
     212             :                                                krb5_kvno kvno,
     213             :                                                const char *princ_s,
     214             :                                                krb5_enctype enctype,
     215             :                                                krb5_data password)
     216             : {
     217             :         krb5_keyblock *keyp;
     218             :         krb5_keytab_entry kt_entry;
     219             :         krb5_error_code ret;
     220           0 :         krb5_principal salt_princ = NULL;
     221             :         char *salt_princ_s;
     222             : 
     223             :         /* remove duplicates first ... */
     224           0 :         ret = libnet_keytab_remove_entries(context, keytab, princ_s, kvno,
     225             :                                            enctype, false);
     226           0 :         if (ret) {
     227           0 :                 DEBUG(1, ("libnet_keytab_remove_entries failed: %s\n",
     228             :                           error_message(ret)));
     229             :         }
     230             : 
     231           0 :         ZERO_STRUCT(kt_entry);
     232             : 
     233           0 :         kt_entry.vno = kvno;
     234             : 
     235           0 :         ret = smb_krb5_parse_name(context, princ_s, &kt_entry.principal);
     236           0 :         if (ret) {
     237           0 :                 DEBUG(1, ("smb_krb5_parse_name(%s) failed (%s)\n",
     238             :                           princ_s, error_message(ret)));
     239           0 :                 return ret;
     240             :         }
     241             : 
     242           0 :         keyp = KRB5_KT_KEY(&kt_entry);
     243             : 
     244           0 :         salt_princ_s = kerberos_secrets_fetch_salt_princ();
     245           0 :         if (salt_princ_s == NULL) {
     246           0 :                 ret = KRB5KRB_ERR_GENERIC;
     247           0 :                 goto done;
     248             :         }
     249             : 
     250           0 :         ret = krb5_parse_name(context, salt_princ_s, &salt_princ);
     251           0 :         SAFE_FREE(salt_princ_s);
     252           0 :         if (ret != 0) {
     253           0 :                 ret = KRB5KRB_ERR_GENERIC;
     254           0 :                 goto done;
     255             :         }
     256             : 
     257           0 :         ret = create_kerberos_key_from_string(context,
     258             :                                               kt_entry.principal,
     259             :                                               salt_princ,
     260             :                                               &password,
     261             :                                               keyp,
     262             :                                               enctype,
     263             :                                               true);
     264           0 :         krb5_free_principal(context, salt_princ);
     265           0 :         if (ret != 0) {
     266           0 :                 ret = KRB5KRB_ERR_GENERIC;
     267           0 :                 goto done;
     268             :         }
     269             : 
     270           0 :         ret = krb5_kt_add_entry(context, keytab, &kt_entry);
     271           0 :         if (ret) {
     272           0 :                 DEBUG(1, ("adding entry to keytab failed (%s)\n",
     273             :                           error_message(ret)));
     274             :         }
     275             : 
     276           0 : done:
     277           0 :         krb5_free_keyblock_contents(context, keyp);
     278           0 :         krb5_free_principal(context, kt_entry.principal);
     279           0 :         ZERO_STRUCT(kt_entry);
     280           0 :         smb_krb5_kt_free_entry(context, &kt_entry);
     281             : 
     282           0 :         return ret;
     283             : }
     284             : 
     285           0 : krb5_error_code libnet_keytab_add(struct libnet_keytab_context *ctx)
     286             : {
     287           0 :         krb5_error_code ret = 0;
     288             :         uint32_t i;
     289             : 
     290             : 
     291           0 :         if (ctx->clean_old_entries) {
     292           0 :                 DEBUG(0, ("cleaning old entries...\n"));
     293           0 :                 for (i=0; i < ctx->count; i++) {
     294           0 :                         struct libnet_keytab_entry *entry = &ctx->entries[i];
     295             : 
     296           0 :                         ret = libnet_keytab_remove_entries(ctx->context,
     297             :                                                            ctx->keytab,
     298             :                                                            entry->principal,
     299             :                                                            0,
     300             :                                                            entry->enctype,
     301             :                                                            true);
     302           0 :                         if (ret) {
     303           0 :                                 DEBUG(1,("libnet_keytab_add: Failed to remove "
     304             :                                          "old entries for %s (enctype %u): %s\n",
     305             :                                          entry->principal, entry->enctype,
     306             :                                          error_message(ret)));
     307           0 :                                 return ret;
     308             :                         }
     309             :                 }
     310             :         }
     311             : 
     312           0 :         for (i=0; i<ctx->count; i++) {
     313             : 
     314           0 :                 struct libnet_keytab_entry *entry = &ctx->entries[i];
     315             :                 krb5_data password;
     316             : 
     317           0 :                 ZERO_STRUCT(password);
     318           0 :                 password.data = (char *)entry->password.data;
     319           0 :                 password.length = entry->password.length;
     320             : 
     321           0 :                 ret = libnet_keytab_add_entry(ctx->context,
     322             :                                               ctx->keytab,
     323           0 :                                               entry->kvno,
     324             :                                               entry->principal,
     325             :                                               entry->enctype,
     326             :                                               password);
     327           0 :                 if (ret) {
     328           0 :                         DEBUG(1,("libnet_keytab_add: "
     329             :                                 "Failed to add entry to keytab file\n"));
     330           0 :                         return ret;
     331             :                 }
     332             :         }
     333             : 
     334           0 :         return ret;
     335             : }
     336             : 
     337           0 : struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *ctx,
     338             :                                                  const char *principal,
     339             :                                                  int kvno,
     340             :                                                  const krb5_enctype enctype,
     341             :                                                  TALLOC_CTX *mem_ctx)
     342             : {
     343           0 :         krb5_error_code ret = 0;
     344             :         krb5_kt_cursor cursor;
     345             :         krb5_keytab_entry kt_entry;
     346           0 :         struct libnet_keytab_entry *entry = NULL;
     347             : 
     348           0 :         ZERO_STRUCT(kt_entry);
     349           0 :         ZERO_STRUCT(cursor);
     350             : 
     351           0 :         ret = krb5_kt_start_seq_get(ctx->context, ctx->keytab, &cursor);
     352           0 :         if (ret) {
     353           0 :                 DEBUG(10, ("krb5_kt_start_seq_get failed: %s\n",
     354             :                           error_message(ret)));
     355           0 :                 return NULL;
     356             :         }
     357             : 
     358           0 :         while (krb5_kt_next_entry(ctx->context, ctx->keytab, &kt_entry, &cursor) == 0)
     359           0 :         {
     360             :                 krb5_keyblock *keyp;
     361           0 :                 char *princ_s = NULL;
     362             : 
     363           0 :                 entry = NULL;
     364             : 
     365           0 :                 if (kt_entry.vno != kvno) {
     366           0 :                         goto cont;
     367             :                 }
     368             : 
     369           0 :                 keyp = KRB5_KT_KEY(&kt_entry);
     370             : 
     371           0 :                 if (KRB5_KEY_TYPE(keyp) != enctype) {
     372           0 :                         goto cont;
     373             :                 }
     374             : 
     375           0 :                 entry = talloc_zero(mem_ctx, struct libnet_keytab_entry);
     376           0 :                 if (!entry) {
     377           0 :                         DEBUG(3, ("talloc failed\n"));
     378           0 :                         goto fail;
     379             :                 }
     380             : 
     381           0 :                 ret = smb_krb5_unparse_name(entry, ctx->context, kt_entry.principal,
     382             :                                             &princ_s);
     383           0 :                 if (ret) {
     384           0 :                         goto cont;
     385             :                 }
     386             : 
     387           0 :                 if (strcmp(principal, princ_s) != 0) {
     388           0 :                         goto cont;
     389             :                 }
     390             : 
     391           0 :                 entry->principal = talloc_strdup(entry, princ_s);
     392           0 :                 if (!entry->principal) {
     393           0 :                         DEBUG(3, ("talloc_strdup_failed\n"));
     394           0 :                         goto fail;
     395             :                 }
     396             : 
     397           0 :                 entry->name = talloc_move(entry, &princ_s);
     398             : 
     399           0 :                 entry->password = data_blob_talloc(entry, KRB5_KEY_DATA(keyp),
     400             :                                                    KRB5_KEY_LENGTH(keyp));
     401           0 :                 if (!entry->password.data) {
     402           0 :                         DEBUG(3, ("data_blob_talloc failed\n"));
     403           0 :                         goto fail;
     404             :                 }
     405             : 
     406           0 :                 DEBUG(10, ("found entry\n"));
     407             : 
     408           0 :                 smb_krb5_kt_free_entry(ctx->context, &kt_entry);
     409           0 :                 break;
     410             : 
     411           0 : fail:
     412           0 :                 smb_krb5_kt_free_entry(ctx->context, &kt_entry);
     413           0 :                 TALLOC_FREE(entry);
     414           0 :                 break;
     415             : 
     416           0 : cont:
     417           0 :                 smb_krb5_kt_free_entry(ctx->context, &kt_entry);
     418           0 :                 TALLOC_FREE(entry);
     419           0 :                 continue;
     420             :         }
     421             : 
     422           0 :         krb5_kt_end_seq_get(ctx->context, ctx->keytab, &cursor);
     423           0 :         return entry;
     424             : }
     425             : 
     426             : /**
     427             :  * Helper function to add data to the list
     428             :  * of keytab entries. It builds the prefix from the input.
     429             :  */
     430           0 : NTSTATUS libnet_keytab_add_to_keytab_entries(TALLOC_CTX *mem_ctx,
     431             :                                              struct libnet_keytab_context *ctx,
     432             :                                              uint32_t kvno,
     433             :                                              const char *name,
     434             :                                              const char *prefix,
     435             :                                              const krb5_enctype enctype,
     436             :                                              DATA_BLOB blob)
     437             : {
     438             :         struct libnet_keytab_entry entry;
     439             : 
     440           0 :         entry.kvno = kvno;
     441           0 :         entry.name = talloc_strdup(mem_ctx, name);
     442           0 :         entry.principal = talloc_asprintf(mem_ctx, "%s%s%s@%s",
     443             :                                           prefix ? prefix : "",
     444             :                                           prefix ? "/" : "",
     445             :                                           name, ctx->dns_domain_name);
     446           0 :         entry.enctype = enctype;
     447           0 :         entry.password = blob;
     448           0 :         NT_STATUS_HAVE_NO_MEMORY(entry.name);
     449           0 :         NT_STATUS_HAVE_NO_MEMORY(entry.principal);
     450           0 :         NT_STATUS_HAVE_NO_MEMORY(entry.password.data);
     451             : 
     452           0 :         ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry,
     453             :                      &ctx->entries, &ctx->count);
     454           0 :         NT_STATUS_HAVE_NO_MEMORY(ctx->entries);
     455             : 
     456           0 :         return NT_STATUS_OK;
     457             : }
     458             : 
     459             : #endif /* HAVE_KRB5 */

Generated by: LCOV version 1.13