LCOV - code coverage report
Current view: top level - source3/libnet - libnet_dssync_keytab.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 0 544 0.0 %
Date: 2024-05-31 13:13:24 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Guenther Deschner <gd@samba.org> 2008
       5             :    Copyright (C) Michael Adam 2008
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "smb_krb5.h"
      23             : #include "libnet/libnet_dssync.h"
      24             : #include "libnet/libnet_keytab.h"
      25             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      26             : #include "lib/crypto/md4.h"
      27             : 
      28             : #if defined(HAVE_ADS)
      29             : 
      30           0 : static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
      31             :                                struct replUpToDateVectorBlob **pold_utdv)
      32             : {
      33           0 :         krb5_error_code ret = 0;
      34           0 :         struct libnet_keytab_context *keytab_ctx;
      35           0 :         struct libnet_keytab_entry *entry;
      36           0 :         struct replUpToDateVectorBlob *old_utdv = NULL;
      37           0 :         char *principal;
      38             : 
      39           0 :         ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx);
      40           0 :         if (ret) {
      41           0 :                 return krb5_to_nt_status(ret);
      42             :         }
      43             : 
      44           0 :         keytab_ctx->dns_domain_name = ctx->dns_domain_name;
      45           0 :         keytab_ctx->clean_old_entries = ctx->clean_old_entries;
      46           0 :         ctx->private_data = keytab_ctx;
      47             : 
      48           0 :         principal = talloc_asprintf(mem_ctx, "UTDV/%s@%s",
      49             :                                     ctx->nc_dn, ctx->dns_domain_name);
      50           0 :         NT_STATUS_HAVE_NO_MEMORY(principal);
      51             : 
      52           0 :         entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL,
      53             :                                      mem_ctx);
      54           0 :         if (entry) {
      55           0 :                 enum ndr_err_code ndr_err;
      56           0 :                 old_utdv = talloc(mem_ctx, struct replUpToDateVectorBlob);
      57             : 
      58           0 :                 ndr_err = ndr_pull_struct_blob(&entry->password, old_utdv, old_utdv,
      59             :                                 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
      60           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      61           0 :                         NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
      62           0 :                         ctx->error_message = talloc_asprintf(ctx,
      63             :                                         "Failed to pull UpToDateVector: %s",
      64             :                                         nt_errstr(status));
      65           0 :                         return status;
      66             :                 }
      67             : 
      68           0 :                 if (DEBUGLEVEL >= 10) {
      69           0 :                         NDR_PRINT_DEBUG(replUpToDateVectorBlob, old_utdv);
      70             :                 }
      71             :         }
      72             : 
      73           0 :         if (pold_utdv) {
      74           0 :                 *pold_utdv = old_utdv;
      75             :         }
      76             : 
      77           0 :         return NT_STATUS_OK;
      78             : }
      79             : 
      80           0 : static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
      81             :                               struct replUpToDateVectorBlob *new_utdv)
      82             : {
      83           0 :         NTSTATUS status = NT_STATUS_OK;
      84           0 :         krb5_error_code ret = 0;
      85           0 :         struct libnet_keytab_context *keytab_ctx =
      86             :                 (struct libnet_keytab_context *)ctx->private_data;
      87             : 
      88           0 :         if (new_utdv) {
      89           0 :                 enum ndr_err_code ndr_err;
      90           0 :                 DATA_BLOB blob;
      91             : 
      92           0 :                 if (DEBUGLEVEL >= 10) {
      93           0 :                         NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv);
      94             :                 }
      95             : 
      96           0 :                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, new_utdv,
      97             :                                 (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob);
      98           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      99           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     100           0 :                         ctx->error_message = talloc_asprintf(ctx,
     101             :                                         "Failed to push UpToDateVector: %s",
     102             :                                         nt_errstr(status));
     103           0 :                         goto done;
     104             :                 }
     105             : 
     106           0 :                 status = libnet_keytab_add_to_keytab_entries(mem_ctx, keytab_ctx, 0,
     107             :                                                              ctx->nc_dn, "UTDV",
     108             :                                                              ENCTYPE_NULL,
     109             :                                                              blob);
     110           0 :                 if (!NT_STATUS_IS_OK(status)) {
     111           0 :                         goto done;
     112             :                 }
     113             :         }
     114             : 
     115           0 :         ret = libnet_keytab_add(keytab_ctx);
     116           0 :         if (ret) {
     117           0 :                 status = krb5_to_nt_status(ret);
     118           0 :                 ctx->error_message = talloc_asprintf(ctx,
     119             :                         "Failed to add entries to keytab %s: %s",
     120             :                         keytab_ctx->keytab_name, error_message(ret));
     121           0 :                 goto done;
     122             :         }
     123             : 
     124           0 :         ctx->result_message = talloc_asprintf(ctx,
     125             :                 "Vampired %d accounts to keytab %s",
     126             :                 keytab_ctx->count,
     127             :                 keytab_ctx->keytab_name);
     128             : 
     129           0 : done:
     130           0 :         TALLOC_FREE(keytab_ctx);
     131           0 :         return status;
     132             : }
     133             : 
     134             : /****************************************************************
     135             : ****************************************************************/
     136             : 
     137           0 : static  NTSTATUS parse_supplemental_credentials(TALLOC_CTX *mem_ctx,
     138             :                         const DATA_BLOB *blob,
     139             :                         struct package_PrimaryKerberosCtr3 **pkb3,
     140             :                         struct package_PrimaryKerberosCtr4 **pkb4)
     141             : {
     142           0 :         NTSTATUS status;
     143           0 :         enum ndr_err_code ndr_err;
     144           0 :         struct supplementalCredentialsBlob scb;
     145           0 :         struct supplementalCredentialsPackage *scpk = NULL;
     146           0 :         DATA_BLOB scpk_blob;
     147           0 :         struct package_PrimaryKerberosBlob *pkb;
     148           0 :         bool newer_keys = false;
     149           0 :         uint32_t j;
     150             : 
     151           0 :         ndr_err = ndr_pull_struct_blob_all(blob, mem_ctx, &scb,
     152             :                         (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
     153           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     154           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     155           0 :                 goto done;
     156             :         }
     157           0 :         if ((scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE)
     158           0 :             && (scb.sub.num_packages != 0))
     159             :         {
     160           0 :                 if (DEBUGLEVEL >= 10) {
     161           0 :                         NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
     162             :                 }
     163           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     164           0 :                 goto done;
     165             :         }
     166           0 :         for (j=0; j < scb.sub.num_packages; j++) {
     167           0 :                 if (strcmp("Primary:Kerberos-Newer-Keys",
     168           0 :                     scb.sub.packages[j].name) == 0)
     169             :                 {
     170           0 :                         scpk = &scb.sub.packages[j];
     171           0 :                         if (!scpk->data || !scpk->data[0]) {
     172           0 :                                 scpk = NULL;
     173           0 :                                 continue;
     174             :                         }
     175           0 :                         newer_keys = true;
     176           0 :                         break;
     177           0 :                 } else  if (strcmp("Primary:Kerberos",
     178           0 :                                    scb.sub.packages[j].name) == 0)
     179             :                 {
     180             :                         /*
     181             :                          * grab this but don't break here:
     182             :                          * there might still be newer-keys ...
     183             :                          */
     184           0 :                         scpk = &scb.sub.packages[j];
     185           0 :                         if (!scpk->data || !scpk->data[0]) {
     186           0 :                                 scpk = NULL;
     187             :                         }
     188             :                 }
     189             :         }
     190             : 
     191           0 :         if (!scpk) {
     192             :                 /* no data */
     193           0 :                 status = NT_STATUS_OK;
     194           0 :                 goto done;
     195             :         }
     196             : 
     197           0 :         scpk_blob = strhex_to_data_blob(mem_ctx, scpk->data);
     198           0 :         if (!scpk_blob.data) {
     199           0 :                 status = NT_STATUS_NO_MEMORY;
     200           0 :                 goto done;
     201             :         }
     202             : 
     203           0 :         pkb = talloc_zero(mem_ctx, struct package_PrimaryKerberosBlob);
     204           0 :         if (!pkb) {
     205           0 :                 status = NT_STATUS_NO_MEMORY;
     206           0 :                 goto done;
     207             :         }
     208           0 :         ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, pkb,
     209             :                         (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
     210           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     211           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     212           0 :                 goto done;
     213             :         }
     214             : 
     215           0 :         if (!newer_keys && pkb->version != 3) {
     216           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     217           0 :                 goto done;
     218             :         }
     219             : 
     220           0 :         if (newer_keys && pkb->version != 4) {
     221           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     222           0 :                 goto done;
     223             :         }
     224             : 
     225           0 :         if (pkb->version == 4 && pkb4) {
     226           0 :                 *pkb4 = &pkb->ctr.ctr4;
     227           0 :         } else if (pkb->version == 3 && pkb3) {
     228           0 :                 *pkb3 = &pkb->ctr.ctr3;
     229             :         }
     230             : 
     231           0 :         status = NT_STATUS_OK;
     232             : 
     233           0 : done:
     234           0 :         return status;
     235             : }
     236             : 
     237           0 : static NTSTATUS store_or_fetch_attribute(TALLOC_CTX *mem_ctx,
     238             :                                          struct libnet_keytab_context *ctx,
     239             :                                          const char *object_dn,
     240             :                                          const char *attr,
     241             :                                          char **value)
     242             : {
     243           0 :         DATA_BLOB blob = { .length = 0, };
     244           0 :         NTSTATUS status;
     245             : 
     246           0 :         if (*value == NULL) {
     247             :                 /* look into keytab ... */
     248           0 :                 struct libnet_keytab_entry *entry = NULL;
     249           0 :                 char *principal = NULL;
     250             : 
     251           0 :                 D_DEBUG("looking for %s/%s@%s in keytayb...\n",
     252             :                         attr, object_dn, ctx->dns_domain_name);
     253             : 
     254           0 :                 principal = talloc_asprintf(mem_ctx,
     255             :                                             "%s/%s@%s",
     256             :                                             attr,
     257             :                                             object_dn,
     258             :                                             ctx->dns_domain_name);
     259           0 :                 if (principal == NULL) {
     260           0 :                         return NT_STATUS_NO_MEMORY;
     261             :                 }
     262           0 :                 entry = libnet_keytab_search(ctx,
     263             :                                              principal,
     264             :                                              0,
     265             :                                              ENCTYPE_NULL,
     266             :                                              mem_ctx);
     267           0 :                 if (entry != NULL) {
     268           0 :                         *value = talloc_strndup(mem_ctx,
     269           0 :                                                 (char *)entry->password.data,
     270             :                                                 entry->password.length);
     271           0 :                         if (*value == NULL) {
     272           0 :                                 return NT_STATUS_NO_MEMORY;
     273             :                         }
     274           0 :                         D_DEBUG("found %s: %s\n", attr, *value);
     275           0 :                         TALLOC_FREE(entry);
     276             :                 } else {
     277           0 :                         *value = NULL;
     278           0 :                         D_DEBUG("entry not found\n");
     279             :                 }
     280           0 :                 TALLOC_FREE(principal);
     281           0 :                 return NT_STATUS_OK;
     282             :         }
     283             : 
     284           0 :         blob = data_blob_string_const_null(*value);
     285           0 :         blob = data_blob_dup_talloc(mem_ctx, blob);
     286           0 :         if (blob.data == NULL) {
     287           0 :                 return NT_STATUS_NO_MEMORY;
     288             :         }
     289             : 
     290           0 :         status = libnet_keytab_add_to_keytab_entries(mem_ctx,
     291             :                                                      ctx,
     292             :                                                      0,
     293             :                                                      object_dn,
     294             :                                                      attr,
     295             :                                                      ENCTYPE_NULL,
     296             :                                                      blob);
     297           0 :         if (!NT_STATUS_IS_OK(status)) {
     298           0 :                 return status;
     299             :         }
     300             : 
     301           0 :         return NT_STATUS_OK;
     302             : }
     303             : 
     304           0 : static NTSTATUS parse_user(TALLOC_CTX *mem_ctx,
     305             :                            struct libnet_keytab_context *ctx,
     306             :                            struct drsuapi_DsReplicaObjectListItemEx *cur)
     307             : {
     308           0 :         NTSTATUS status = NT_STATUS_OK;
     309           0 :         uchar nt_passwd[16];
     310           0 :         DATA_BLOB *blob;
     311           0 :         int i = 0;
     312           0 :         struct drsuapi_DsReplicaAttribute *attr;
     313           0 :         bool got_pwd = false;
     314             : 
     315           0 :         struct package_PrimaryKerberosCtr3 *pkb3 = NULL;
     316           0 :         struct package_PrimaryKerberosCtr4 *pkb4 = NULL;
     317             : 
     318           0 :         char *object_dn = NULL;
     319           0 :         char *upn = NULL;
     320           0 :         char **spn = NULL;
     321           0 :         uint32_t num_spns = 0;
     322           0 :         char *name = NULL;
     323           0 :         uint32_t kvno = 0;
     324           0 :         uint32_t uacc = 0;
     325           0 :         uint32_t sam_type = 0;
     326             : 
     327           0 :         uint32_t pwd_history_len = 0;
     328           0 :         uint8_t *pwd_history = NULL;
     329             : 
     330           0 :         ZERO_STRUCT(nt_passwd);
     331             : 
     332           0 :         object_dn = talloc_strdup(mem_ctx, cur->object.identifier->dn);
     333           0 :         if (!object_dn) {
     334           0 :                 return NT_STATUS_NO_MEMORY;
     335             :         }
     336             : 
     337           0 :         DEBUG(3, ("parsing user '%s'\n", object_dn));
     338             : 
     339           0 :         for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
     340             : 
     341           0 :                 attr = &cur->object.attribute_ctr.attributes[i];
     342             : 
     343           0 :                 if (attr->attid == DRSUAPI_ATTID_servicePrincipalName) {
     344           0 :                         uint32_t count;
     345           0 :                         num_spns = attr->value_ctr.num_values;
     346           0 :                         spn = talloc_array(mem_ctx, char *, num_spns);
     347           0 :                         for (count = 0; count < num_spns; count++) {
     348           0 :                                 blob = attr->value_ctr.values[count].blob;
     349           0 :                                 if (blob == NULL) {
     350           0 :                                         continue;
     351             :                                 }
     352           0 :                                 pull_string_talloc(spn, NULL, 0,
     353           0 :                                                    &spn[count],
     354           0 :                                                    blob->data, blob->length,
     355             :                                                    STR_UNICODE);
     356             :                         }
     357             :                 }
     358             : 
     359           0 :                 if (attr->attid == DRSUAPI_ATTID_unicodePwd &&
     360           0 :                     cur->meta_data_ctr != NULL &&
     361           0 :                     cur->meta_data_ctr->count ==
     362           0 :                     cur->object.attribute_ctr.num_attributes)
     363             :                 {
     364             :                         /*
     365             :                          * pick the kvno from the unicodePwd
     366             :                          * meta data, even without a unicodePwd blob
     367             :                          */
     368           0 :                         kvno = cur->meta_data_ctr->meta_data[i].version;
     369             :                 }
     370             : 
     371           0 :                 if (attr->value_ctr.num_values != 1) {
     372           0 :                         continue;
     373             :                 }
     374             : 
     375           0 :                 if (!attr->value_ctr.values[0].blob) {
     376           0 :                         continue;
     377             :                 }
     378             : 
     379           0 :                 blob = attr->value_ctr.values[0].blob;
     380             : 
     381           0 :                 switch (attr->attid) {
     382           0 :                         case DRSUAPI_ATTID_unicodePwd:
     383             : 
     384           0 :                                 if (blob->length != 16) {
     385           0 :                                         break;
     386             :                                 }
     387             : 
     388           0 :                                 memcpy(&nt_passwd, blob->data, 16);
     389           0 :                                 got_pwd = true;
     390           0 :                                 break;
     391           0 :                         case DRSUAPI_ATTID_ntPwdHistory:
     392           0 :                                 pwd_history_len = blob->length / 16;
     393           0 :                                 pwd_history = blob->data;
     394           0 :                                 break;
     395           0 :                         case DRSUAPI_ATTID_userPrincipalName:
     396           0 :                                 pull_string_talloc(mem_ctx, NULL, 0, &upn,
     397           0 :                                                    blob->data, blob->length,
     398             :                                                    STR_UNICODE);
     399           0 :                                 break;
     400           0 :                         case DRSUAPI_ATTID_sAMAccountName:
     401           0 :                                 pull_string_talloc(mem_ctx, NULL, 0, &name,
     402           0 :                                                    blob->data, blob->length,
     403             :                                                    STR_UNICODE);
     404           0 :                                 break;
     405           0 :                         case DRSUAPI_ATTID_sAMAccountType:
     406           0 :                                 sam_type = IVAL(blob->data, 0);
     407           0 :                                 break;
     408           0 :                         case DRSUAPI_ATTID_userAccountControl:
     409           0 :                                 uacc = IVAL(blob->data, 0);
     410           0 :                                 break;
     411           0 :                         case DRSUAPI_ATTID_supplementalCredentials:
     412           0 :                                 status = parse_supplemental_credentials(mem_ctx,
     413             :                                                                         blob,
     414             :                                                                         &pkb3,
     415             :                                                                         &pkb4);
     416           0 :                                 if (!NT_STATUS_IS_OK(status)) {
     417           0 :                                         DEBUG(2, ("parsing of supplemental "
     418             :                                                   "credentials failed: %s\n",
     419             :                                                   nt_errstr(status)));
     420             :                                 }
     421           0 :                                 break;
     422           0 :                         default:
     423           0 :                                 break;
     424             :                 }
     425             :         }
     426             : 
     427           0 :         status = store_or_fetch_attribute(mem_ctx,
     428             :                                           ctx,
     429             :                                           object_dn,
     430             :                                           "SAMACCOUNTNAME",
     431             :                                           &name);
     432           0 :         if (!NT_STATUS_IS_OK(status)) {
     433           0 :                 DBG_ERR("store_or_fetch_attribute(%s, %s, %s): %s\n",
     434             :                         object_dn, "SAMACCOUNTNAME", name,
     435             :                         nt_errstr(status));
     436           0 :                 return status;
     437             :         }
     438             : 
     439           0 :         if (!name) {
     440           0 :                 DEBUG(10, ("no name (sAMAccountName) found - skipping.\n"));
     441           0 :                 return NT_STATUS_OK;
     442             :         }
     443             : 
     444           0 :         DEBUG(1,("#%02d: %s:%d, ", ctx->count, name, kvno));
     445           0 :         DEBUGADD(1,("sAMAccountType: 0x%08x, userAccountControl: 0x%08x",
     446             :                 sam_type, uacc));
     447           0 :         if (upn) {
     448           0 :                 DEBUGADD(1,(", upn: %s", upn));
     449             :         }
     450           0 :         if (num_spns > 0) {
     451           0 :                 DEBUGADD(1, (", spns: ["));
     452           0 :                 for (i = 0; i < num_spns; i++) {
     453           0 :                         DEBUGADD(1, ("%s%s", spn[i],
     454             :                                      (i+1 == num_spns)?"]":", "));
     455             :                 }
     456             :         }
     457           0 :         DEBUGADD(1,("\n"));
     458             : 
     459           0 :         if (got_pwd) {
     460           0 :                 status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL,
     461             :                                                              ENCTYPE_ARCFOUR_HMAC,
     462             :                                                              data_blob_talloc(mem_ctx, nt_passwd, 16));
     463             : 
     464           0 :                 if (!NT_STATUS_IS_OK(status)) {
     465           0 :                         return status;
     466             :                 }
     467             :         }
     468             : 
     469             :         /* add kerberos keys (if any) */
     470             : 
     471           0 :         if (pkb4) {
     472           0 :                 for (i=0; i < pkb4->num_keys; i++) {
     473           0 :                         if (!pkb4->keys[i].value) {
     474           0 :                                 continue;
     475             :                         }
     476           0 :                         status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno,
     477             :                                                                      name,
     478             :                                                                      NULL,
     479           0 :                                                                      pkb4->keys[i].keytype,
     480           0 :                                                                      *pkb4->keys[i].value);
     481           0 :                         if (!NT_STATUS_IS_OK(status)) {
     482           0 :                                 return status;
     483             :                         }
     484             :                 }
     485           0 :                 for (i=0; i < pkb4->num_old_keys; i++) {
     486           0 :                         if (!pkb4->old_keys[i].value) {
     487           0 :                                 continue;
     488             :                         }
     489           0 :                         status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno - 1,
     490             :                                                                      name,
     491             :                                                                      NULL,
     492           0 :                                                                      pkb4->old_keys[i].keytype,
     493           0 :                                                                      *pkb4->old_keys[i].value);
     494           0 :                         if (!NT_STATUS_IS_OK(status)) {
     495           0 :                                 return status;
     496             :                         }
     497             :                 }
     498           0 :                 for (i=0; i < pkb4->num_older_keys; i++) {
     499           0 :                         if (!pkb4->older_keys[i].value) {
     500           0 :                                 continue;
     501             :                         }
     502           0 :                         status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno - 2,
     503             :                                                                      name,
     504             :                                                                      NULL,
     505           0 :                                                                      pkb4->older_keys[i].keytype,
     506           0 :                                                                      *pkb4->older_keys[i].value);
     507           0 :                         if (!NT_STATUS_IS_OK(status)) {
     508           0 :                                 return status;
     509             :                         }
     510             :                 }
     511             :         }
     512             : 
     513           0 :         if (pkb3) {
     514           0 :                 for (i=0; i < pkb3->num_keys; i++) {
     515           0 :                         if (!pkb3->keys[i].value) {
     516           0 :                                 continue;
     517             :                         }
     518           0 :                         status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, name,
     519             :                                                                      NULL,
     520           0 :                                                                      pkb3->keys[i].keytype,
     521           0 :                                                                      *pkb3->keys[i].value);
     522           0 :                         if (!NT_STATUS_IS_OK(status)) {
     523           0 :                                 return status;
     524             :                         }
     525             :                 }
     526           0 :                 for (i=0; i < pkb3->num_old_keys; i++) {
     527           0 :                         if (!pkb3->old_keys[i].value) {
     528           0 :                                 continue;
     529             :                         }
     530           0 :                         status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno - 1,
     531             :                                                                      name,
     532             :                                                                      NULL,
     533           0 :                                                                      pkb3->old_keys[i].keytype,
     534           0 :                                                                      *pkb3->old_keys[i].value);
     535           0 :                         if (!NT_STATUS_IS_OK(status)) {
     536           0 :                                 return status;
     537             :                         }
     538             :                 }
     539             :         }
     540             : 
     541           0 :         if (kvno < pwd_history_len) {
     542           0 :                 return status;
     543             :         }
     544             : 
     545             :         /* add password history */
     546             : 
     547             :         /* skip first entry */
     548           0 :         if (got_pwd) {
     549           0 :                 kvno--;
     550           0 :                 i = 1;
     551             :         } else {
     552           0 :                 i = 0;
     553             :         }
     554             : 
     555           0 :         for (; i<pwd_history_len; i++) {
     556           0 :                 status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno--, name, NULL,
     557             :                                                              ENCTYPE_ARCFOUR_HMAC,
     558           0 :                                                              data_blob_talloc(mem_ctx, &pwd_history[i*16], 16));
     559           0 :                 if (!NT_STATUS_IS_OK(status)) {
     560           0 :                         break;
     561             :                 }
     562             :         }
     563             : 
     564           0 :         return status;
     565             : }
     566             : 
     567           0 : static NTSTATUS parse_AuthenticationInformation(TALLOC_CTX *mem_ctx,
     568             :                                                 struct libnet_keytab_context *ctx,
     569             :                                                 const char *dn,
     570             :                                                 const char *trust_name,
     571             :                                                 const char *attr_name,
     572             :                                                 const char *salt_principal,
     573             :                                                 const char *type,
     574             :                                                 uint32_t *kvno,
     575             :                                                 const struct AuthenticationInformationArray *ia)
     576             : {
     577           0 :         uint32_t i;
     578           0 :         struct samr_Password _nthash = {{ 0, }};
     579           0 :         const struct samr_Password *nthash = NULL;
     580           0 :         const struct AuthInfoClear *clear = NULL;
     581           0 :         DATA_BLOB password_utf8 = data_blob_null;
     582             : 
     583           0 :         for (i = 0; i < ia->count; i++) {
     584           0 :                 const struct AuthenticationInformation *a = &ia->array[i];
     585             : 
     586           0 :                 switch (a->AuthType) {
     587           0 :                 case TRUST_AUTH_TYPE_VERSION:
     588           0 :                         *kvno = a->AuthInfo.version.version;
     589           0 :                         break;
     590           0 :                 case TRUST_AUTH_TYPE_NT4OWF:
     591           0 :                         nthash = &a->AuthInfo.nt4owf.password;
     592           0 :                         break;
     593           0 :                 case TRUST_AUTH_TYPE_CLEAR:
     594           0 :                         clear = &a->AuthInfo.clear;
     595           0 :                         break;
     596           0 :                 default:
     597           0 :                         break;
     598             :                 }
     599             :         }
     600             : 
     601           0 :         if (clear != NULL && clear->size != 0) {
     602           0 :                 DATA_BLOB password_utf16 = data_blob_null;
     603           0 :                 bool ok;
     604             : 
     605           0 :                 password_utf16 = data_blob_const(clear->password,
     606           0 :                                                  clear->size);
     607             : 
     608           0 :                 if (nthash == NULL) {
     609           0 :                         mdfour(_nthash.hash,
     610           0 :                                password_utf16.data,
     611           0 :                                password_utf16.length);
     612           0 :                         nthash = &_nthash;
     613             :                 }
     614             : 
     615           0 :                 ok = convert_string_talloc(mem_ctx,
     616             :                                            CH_UTF16MUNGED, CH_UTF8,
     617           0 :                                            password_utf16.data,
     618             :                                            password_utf16.length,
     619             :                                            (void *)&password_utf8.data,
     620             :                                            &password_utf8.length);
     621           0 :                 if (!ok) {
     622           0 :                         return NT_STATUS_NO_MEMORY;
     623             :                 }
     624             :         }
     625             : 
     626           0 :         if (password_utf8.length != 0) {
     627           0 :                 krb5_principal salt_princ = NULL;
     628           0 :                 krb5_data salt = { 0, };
     629           0 :                 krb5_data cleartext_data = { 0, };
     630           0 :                 krb5_enctype enctypes[] = {
     631             :                         ENCTYPE_AES256_CTS_HMAC_SHA1_96,
     632             :                         ENCTYPE_AES128_CTS_HMAC_SHA1_96,
     633             :                 };
     634           0 :                 size_t ei;
     635           0 :                 krb5_error_code kret;
     636           0 :                 NTSTATUS status;
     637             : 
     638           0 :                 kret = smb_krb5_parse_name(ctx->context,
     639             :                                            salt_principal,
     640             :                                            &salt_princ);
     641           0 :                 if (kret != 0) {
     642           0 :                         return NT_STATUS_NO_MEMORY;
     643             :                 }
     644             : 
     645           0 :                 cleartext_data.data = discard_const_p(char, password_utf8.data);
     646           0 :                 cleartext_data.length = password_utf8.length;
     647             : 
     648           0 :                 kret = smb_krb5_get_pw_salt(ctx->context,
     649             :                                             salt_princ,
     650             :                                             &salt);
     651           0 :                 if (kret != 0) {
     652           0 :                         krb5_free_principal(ctx->context, salt_princ);
     653           0 :                         return NT_STATUS_NO_MEMORY;
     654             :                 }
     655             : 
     656           0 :                 for (ei = 0; ei < ARRAY_SIZE(enctypes); ei++) {
     657           0 :                         krb5_keyblock keyb = { 0, };
     658           0 :                         DATA_BLOB blob = data_blob_null;
     659             : 
     660           0 :                         kret = smb_krb5_create_key_from_string(ctx->context,
     661             :                                                                salt_princ,
     662             :                                                                &salt,
     663             :                                                                &cleartext_data,
     664             :                                                                enctypes[ei],
     665             :                                                                &keyb);
     666           0 :                         if (kret != 0) {
     667           0 :                                 smb_krb5_free_data_contents(ctx->context, &salt);
     668           0 :                                 krb5_free_principal(ctx->context, salt_princ);
     669           0 :                                 return NT_STATUS_NO_MEMORY;
     670             :                         }
     671             : 
     672           0 :                         blob = data_blob_talloc(mem_ctx,
     673             :                                                 KRB5_KEY_DATA(&keyb),
     674             :                                                 KRB5_KEY_LENGTH(&keyb));
     675           0 :                         krb5_free_keyblock_contents(ctx->context, &keyb);
     676             : 
     677           0 :                         status = libnet_keytab_add_to_keytab_entries(mem_ctx,
     678             :                                                                      ctx,
     679             :                                                                      *kvno,
     680             :                                                                      trust_name,
     681             :                                                                      attr_name,
     682             :                                                                      enctypes[ei],
     683             :                                                                      blob);
     684           0 :                         if (!NT_STATUS_IS_OK(status)) {
     685           0 :                                 smb_krb5_free_data_contents(ctx->context, &salt);
     686           0 :                                 krb5_free_principal(ctx->context, salt_princ);
     687           0 :                                 return status;
     688             :                         }
     689             :                 }
     690             : 
     691           0 :                 smb_krb5_free_data_contents(ctx->context, &salt);
     692           0 :                 krb5_free_principal(ctx->context, salt_princ);
     693             :         }
     694             : 
     695           0 :         if (nthash != NULL) {
     696           0 :                 DATA_BLOB blob = data_blob_null;
     697           0 :                 NTSTATUS status;
     698             : 
     699           0 :                 blob = data_blob_talloc(mem_ctx, nthash->hash, sizeof(nthash->hash));
     700             : 
     701           0 :                 status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx,
     702             :                                                              *kvno,
     703             :                                                              trust_name,
     704             :                                                              attr_name,
     705             :                                                              ENCTYPE_ARCFOUR_HMAC,
     706             :                                                              blob);
     707           0 :                 if (!NT_STATUS_IS_OK(status)) {
     708           0 :                         return status;
     709             :                 }
     710             :         }
     711             : 
     712           0 :         return NT_STATUS_OK;
     713             : }
     714             : 
     715           0 : static NTSTATUS parse_trustAuthInOutBlob(TALLOC_CTX *mem_ctx,
     716             :                                          struct libnet_keytab_context *ctx,
     717             :                                          const char *dn,
     718             :                                          const char *trust_name,
     719             :                                          const char *attr_name,
     720             :                                          const char *salt_principal,
     721             :                                          const DATA_BLOB *blob)
     722             : {
     723           0 :         NTSTATUS status;
     724           0 :         enum ndr_err_code ndr_err;
     725           0 :         struct trustAuthInOutBlob taiob;
     726           0 :         uint32_t kvno = 0;
     727             : 
     728           0 :         ndr_err = ndr_pull_struct_blob_all(blob, mem_ctx, &taiob,
     729             :                         (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
     730           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     731           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     732           0 :                 goto done;
     733             :         }
     734             : 
     735           0 :         D_WARNING("# %s %s/%s\n", dn, attr_name, trust_name);
     736             : 
     737           0 :         status = parse_AuthenticationInformation(mem_ctx,
     738             :                                                  ctx,
     739             :                                                  dn,
     740             :                                                  trust_name,
     741             :                                                  attr_name,
     742             :                                                  salt_principal,
     743             :                                                  "current",
     744             :                                                  &kvno,
     745             :                                                  &taiob.current);
     746           0 :         if (!NT_STATUS_IS_OK(status)) {
     747           0 :                 DBG_ERR("parsing of %s %s/current failed: %s\n",
     748             :                         dn, attr_name, nt_errstr(status));
     749             :         }
     750             : 
     751           0 :         kvno -= 1;
     752           0 :         status = parse_AuthenticationInformation(mem_ctx,
     753             :                                                  ctx,
     754             :                                                  dn,
     755             :                                                  trust_name,
     756             :                                                  attr_name,
     757             :                                                  salt_principal,
     758             :                                                  "previous",
     759             :                                                  &kvno,
     760             :                                                  &taiob.previous);
     761           0 :         if (!NT_STATUS_IS_OK(status)) {
     762           0 :                 DBG_ERR("parsing of %s %s/previous failed: %s\n",
     763             :                         dn, attr_name, nt_errstr(status));
     764             :         }
     765             : 
     766           0 :         status = NT_STATUS_OK;
     767           0 : done:
     768           0 :         return status;
     769             : }
     770             : 
     771           0 : static NTSTATUS parse_tdo(TALLOC_CTX *mem_ctx,
     772             :                           struct libnet_keytab_context *ctx,
     773             :                           struct drsuapi_DsReplicaObjectListItemEx *cur)
     774             : {
     775           0 :         uint32_t i;
     776           0 :         const char *dn = cur->object.identifier->dn;
     777           0 :         char *trustPartner = NULL;
     778           0 :         char *flatName = NULL;
     779           0 :         char *cn = NULL;
     780           0 :         char *trust_name = NULL;
     781           0 :         char *trust_realm = NULL;
     782           0 :         char *our_realm = NULL;
     783           0 :         const char *incoming_salt = NULL;
     784           0 :         const char *outgoing_salt = NULL;
     785           0 :         NTSTATUS status;
     786             : 
     787           0 :         D_NOTICE("parsing trust '%s'\n", dn);
     788             : 
     789           0 :         for (i = 0; i < cur->object.attribute_ctr.num_attributes; i++) {
     790           0 :                 struct drsuapi_DsReplicaAttribute *attr =
     791           0 :                         &cur->object.attribute_ctr.attributes[i];
     792           0 :                 const DATA_BLOB *blob = NULL;
     793             : 
     794           0 :                 if (attr->value_ctr.num_values != 1) {
     795           0 :                         continue;
     796             :                 }
     797             : 
     798           0 :                 if (attr->value_ctr.values[0].blob == NULL) {
     799           0 :                         continue;
     800             :                 }
     801             : 
     802           0 :                 blob = attr->value_ctr.values[0].blob;
     803             : 
     804           0 :                 switch (attr->attid) {
     805           0 :                 case DRSUAPI_ATTID_trustPartner:
     806           0 :                         pull_string_talloc(mem_ctx, NULL, 0, &trustPartner,
     807           0 :                                            blob->data, blob->length,
     808             :                                            STR_UNICODE);
     809           0 :                         break;
     810           0 :                 case DRSUAPI_ATTID_flatName:
     811           0 :                         pull_string_talloc(mem_ctx, NULL, 0, &flatName,
     812           0 :                                            blob->data, blob->length,
     813             :                                            STR_UNICODE);
     814           0 :                         break;
     815           0 :                 case DRSUAPI_ATTID_cn:
     816           0 :                         pull_string_talloc(mem_ctx, NULL, 0, &cn,
     817           0 :                                            blob->data, blob->length,
     818             :                                            STR_UNICODE);
     819           0 :                         break;
     820           0 :                 default:
     821           0 :                         break;
     822             :                 }
     823             :         }
     824             : 
     825           0 :         if (trustPartner != NULL) {
     826           0 :                 trust_name = trustPartner;
     827           0 :         } else if (flatName != NULL) {
     828           0 :                 trust_name = flatName;
     829             :         } else {
     830           0 :                 trust_name = cn;
     831             :         }
     832             : 
     833           0 :         status = store_or_fetch_attribute(mem_ctx,
     834             :                                           ctx,
     835             :                                           dn,
     836             :                                           "REMOTETRUSTNAME",
     837             :                                           &trust_name);
     838           0 :         if (!NT_STATUS_IS_OK(status)) {
     839           0 :                 DBG_ERR("store_or_fetch_attribute(%s, %s, %s): %s\n",
     840             :                         dn, "REMOTETRUSTNAME", trust_name,
     841             :                         nt_errstr(status));
     842           0 :                 return status;
     843             :         }
     844             : 
     845           0 :         if (trust_name == NULL) {
     846           0 :                 D_DEBUG("no trust_name (trustPartner, flatName, cn) found - "
     847             :                         "skipping.\n");
     848           0 :                 return NT_STATUS_OK;
     849             :         }
     850             : 
     851           0 :         trust_realm = strupper_talloc(mem_ctx, trust_name);
     852           0 :         if (trust_realm == NULL) {
     853           0 :                 return NT_STATUS_NO_MEMORY;
     854             :         }
     855           0 :         our_realm = strupper_talloc(mem_ctx, ctx->dns_domain_name);
     856           0 :         if (our_realm == NULL) {
     857           0 :                 return NT_STATUS_NO_MEMORY;
     858             :         }
     859             : 
     860           0 :         incoming_salt = talloc_asprintf(mem_ctx,
     861             :                                         "krbtgt/%s@%s",
     862             :                                         trust_realm,
     863             :                                         our_realm);
     864           0 :         if (incoming_salt == NULL) {
     865           0 :                 return NT_STATUS_NO_MEMORY;
     866             :         }
     867           0 :         outgoing_salt = talloc_asprintf(mem_ctx,
     868             :                                         "krbtgt/%s@%s",
     869             :                                         our_realm,
     870             :                                         trust_realm);
     871           0 :         if (outgoing_salt == NULL) {
     872           0 :                 return NT_STATUS_NO_MEMORY;
     873             :         }
     874             : 
     875           0 :         for (i = 0; i < cur->object.attribute_ctr.num_attributes; i++) {
     876           0 :                 struct drsuapi_DsReplicaAttribute *attr =
     877           0 :                         &cur->object.attribute_ctr.attributes[i];
     878           0 :                 const char *attr_name = NULL;
     879           0 :                 const DATA_BLOB *blob = NULL;
     880           0 :                 const char *salt_principal = NULL;
     881             : 
     882           0 :                 if (attr->value_ctr.num_values != 1) {
     883           0 :                         continue;
     884             :                 }
     885             : 
     886           0 :                 if (attr->value_ctr.values[0].blob == NULL) {
     887           0 :                         continue;
     888             :                 }
     889             : 
     890           0 :                 blob = attr->value_ctr.values[0].blob;
     891             : 
     892           0 :                 switch (attr->attid) {
     893           0 :                 case DRSUAPI_ATTID_trustAuthIncoming:
     894           0 :                         attr_name = "trustAuthIncoming";
     895           0 :                         salt_principal = incoming_salt;
     896           0 :                         break;
     897           0 :                 case DRSUAPI_ATTID_trustAuthOutgoing:
     898           0 :                         attr_name = "trustAuthOutgoing";
     899           0 :                         salt_principal = outgoing_salt;
     900           0 :                         break;
     901           0 :                 default:
     902           0 :                         break;
     903             :                 }
     904             : 
     905           0 :                 if (attr_name == NULL) {
     906           0 :                         continue;
     907             :                 }
     908             : 
     909           0 :                 status = parse_trustAuthInOutBlob(mem_ctx,
     910             :                                                   ctx,
     911             :                                                   dn,
     912             :                                                   trust_name,
     913             :                                                   attr_name,
     914             :                                                   salt_principal,
     915             :                                                   blob);
     916           0 :                 if (!NT_STATUS_IS_OK(status)) {
     917           0 :                         DBG_ERR("parsing of %s attr %s failed: %s\n",
     918             :                                 dn, attr_name, nt_errstr(status));
     919             :                 }
     920             :         }
     921             : 
     922           0 :         return NT_STATUS_OK;
     923             : }
     924             : 
     925           0 : static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
     926             :                              struct libnet_keytab_context *ctx,
     927             :                              struct drsuapi_DsReplicaObjectListItemEx *cur)
     928             : {
     929           0 :         uint32_t i;
     930             : 
     931           0 :         if (cur->object.identifier->dn == NULL) {
     932           0 :                 return NT_STATUS_OK;
     933             :         }
     934             : 
     935           0 :         for (i = 0; i < cur->object.attribute_ctr.num_attributes; i++) {
     936           0 :                 struct drsuapi_DsReplicaAttribute *attr =
     937           0 :                         &cur->object.attribute_ctr.attributes[i];
     938           0 :                 const DATA_BLOB *blob = NULL;
     939           0 :                 uint32_t val;
     940             : 
     941           0 :                 switch (attr->attid) {
     942           0 :                 case DRSUAPI_ATTID_isDeleted:
     943             :                 case DRSUAPI_ATTID_isRecycled:
     944           0 :                         break;
     945           0 :                 default:
     946           0 :                         continue;
     947             :                 }
     948             : 
     949           0 :                 if (attr->value_ctr.num_values != 1) {
     950           0 :                         continue;
     951             :                 }
     952             : 
     953           0 :                 if (attr->value_ctr.values[0].blob == NULL) {
     954           0 :                         continue;
     955             :                 }
     956             : 
     957           0 :                 blob = attr->value_ctr.values[0].blob;
     958             : 
     959           0 :                 if (blob->length != 4) {
     960           0 :                         continue;
     961             :                 }
     962             : 
     963           0 :                 val = PULL_LE_U32(blob->data, 0);
     964           0 :                 if (val != 0) {
     965             :                         /* ignore deleted object */
     966           0 :                         return NT_STATUS_OK;
     967             :                 }
     968             :         }
     969             : 
     970           0 :         for (i = 0; i < cur->object.attribute_ctr.num_attributes; i++) {
     971           0 :                 struct drsuapi_DsReplicaAttribute *attr =
     972           0 :                         &cur->object.attribute_ctr.attributes[i];
     973             : 
     974           0 :                 switch (attr->attid) {
     975           0 :                 case DRSUAPI_ATTID_unicodePwd:
     976             :                 case DRSUAPI_ATTID_ntPwdHistory:
     977             :                 case DRSUAPI_ATTID_supplementalCredentials:
     978           0 :                         return parse_user(mem_ctx, ctx, cur);
     979           0 :                 case DRSUAPI_ATTID_trustAuthIncoming:
     980             :                 case DRSUAPI_ATTID_trustAuthOutgoing:
     981           0 :                         return parse_tdo(mem_ctx, ctx, cur);
     982           0 :                 default:
     983           0 :                         continue;
     984             :                 }
     985             :         }
     986             : 
     987           0 :         return NT_STATUS_OK;
     988             : }
     989             : 
     990           0 : static bool dn_is_in_object_list(struct dssync_context *ctx,
     991             :                                  const char *dn)
     992             : {
     993           0 :         uint32_t count;
     994             : 
     995           0 :         if (ctx->object_count == 0) {
     996           0 :                 return true;
     997             :         }
     998             : 
     999           0 :         for (count = 0; count < ctx->object_count; count++) {
    1000           0 :                 if (strequal(ctx->object_dns[count], dn)) {
    1001           0 :                         return true;
    1002             :                 }
    1003             :         }
    1004             : 
    1005           0 :         return false;
    1006             : }
    1007             : 
    1008             : /****************************************************************
    1009             : ****************************************************************/
    1010             : 
    1011           0 : static NTSTATUS keytab_process_objects(struct dssync_context *ctx,
    1012             :                                        TALLOC_CTX *mem_ctx,
    1013             :                                        struct drsuapi_DsReplicaObjectListItemEx *cur,
    1014             :                                        struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr)
    1015             : {
    1016           0 :         NTSTATUS status = NT_STATUS_OK;
    1017           0 :         struct libnet_keytab_context *keytab_ctx =
    1018             :                 (struct libnet_keytab_context *)ctx->private_data;
    1019             : 
    1020           0 :         for (; cur; cur = cur->next_object) {
    1021             :                 /*
    1022             :                  * When not in single object replication mode,
    1023             :                  * the object_dn list is used as a positive write filter.
    1024             :                  */
    1025           0 :                 if (!ctx->single_object_replication &&
    1026           0 :                     !dn_is_in_object_list(ctx, cur->object.identifier->dn))
    1027             :                 {
    1028           0 :                         continue;
    1029             :                 }
    1030             : 
    1031           0 :                 status = parse_object(mem_ctx, keytab_ctx, cur);
    1032           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1033           0 :                         goto out;
    1034             :                 }
    1035             :         }
    1036             : 
    1037           0 :  out:
    1038           0 :         return status;
    1039             : }
    1040             : 
    1041             : #else
    1042             : 
    1043           0 : static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
    1044             :                                struct replUpToDateVectorBlob **pold_utdv)
    1045             : {
    1046           0 :         return NT_STATUS_NOT_SUPPORTED;
    1047             : }
    1048             : 
    1049           0 : static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
    1050             :                               struct replUpToDateVectorBlob *new_utdv)
    1051             : {
    1052           0 :         return NT_STATUS_NOT_SUPPORTED;
    1053             : }
    1054             : 
    1055           0 : static NTSTATUS keytab_process_objects(struct dssync_context *ctx,
    1056             :                                        TALLOC_CTX *mem_ctx,
    1057             :                                        struct drsuapi_DsReplicaObjectListItemEx *cur,
    1058             :                                        struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr)
    1059             : {
    1060           0 :         return NT_STATUS_NOT_SUPPORTED;
    1061             : }
    1062             : #endif /* defined(HAVE_ADS) */
    1063             : 
    1064             : const struct dssync_ops libnet_dssync_keytab_ops = {
    1065             :         .startup                = keytab_startup,
    1066             :         .process_objects        = keytab_process_objects,
    1067             :         .finish                 = keytab_finish,
    1068             : };

Generated by: LCOV version 1.14