root/source3/libnet/libnet_samsync_keytab.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. keytab_ad_connect
  2. fetch_sam_entry_keytab
  3. init_keytab
  4. fetch_sam_entries_keytab
  5. close_keytab
  6. init_keytab
  7. fetch_sam_entries_keytab
  8. close_keytab

   1 /*
   2    Unix SMB/CIFS implementation.
   3    dump the remote SAM using rpc samsync operations
   4 
   5    Copyright (C) Guenther Deschner 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 "libnet/libnet.h"
  23 
  24 #if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC)
  25 
  26 /****************************************************************
  27 ****************************************************************/
  28 
  29 static NTSTATUS keytab_ad_connect(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  30                                   const char *domain_name,
  31                                   const char *username,
  32                                   const char *password,
  33                                   struct libnet_keytab_context *ctx)
  34 {
  35         NTSTATUS status;
  36         ADS_STATUS ad_status;
  37         ADS_STRUCT *ads;
  38         struct netr_DsRGetDCNameInfo *info = NULL;
  39         const char *dc;
  40 
  41         status = dsgetdcname(mem_ctx, NULL, domain_name, NULL, NULL, 0, &info);
  42         if (!NT_STATUS_IS_OK(status)) {
  43                 return status;
  44         }
  45 
  46         dc = strip_hostname(info->dc_unc);
  47 
  48         ads = ads_init(NULL, domain_name, dc);
  49         NT_STATUS_HAVE_NO_MEMORY(ads);
  50 
  51         if (getenv(KRB5_ENV_CCNAME) == NULL) {
  52                 setenv(KRB5_ENV_CCNAME, "MEMORY:libnet_samsync_keytab", 1);
  53         }
  54 
  55         ads->auth.user_name = SMB_STRDUP(username);
  56         ads->auth.password = SMB_STRDUP(password);
  57 
  58         ad_status = ads_connect_user_creds(ads);
  59         if (!ADS_ERR_OK(ad_status)) {
  60                 return NT_STATUS_UNSUCCESSFUL;
  61         }
  62 
  63         ctx->ads = ads;
  64 
  65         ctx->dns_domain_name = talloc_strdup_upper(mem_ctx, ads->config.realm);
  66         NT_STATUS_HAVE_NO_MEMORY(ctx->dns_domain_name);
  67 
  68         return NT_STATUS_OK;
  69 }
  70 
  71 /****************************************************************
  72 ****************************************************************/
  73 
  74 static NTSTATUS fetch_sam_entry_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  75                                        enum netr_SamDatabaseID database_id,
  76                                        uint32_t rid,
  77                                        struct netr_DELTA_USER *r,
  78                                        struct libnet_keytab_context *ctx)
  79 {
  80         NTSTATUS status;
  81         uint32_t kvno = 0;
  82         DATA_BLOB blob;
  83 
  84         if (memcmp(r->ntpassword.hash, ctx->zero_buf, 16) == 0) {
  85                 return NT_STATUS_OK;
  86         }
  87 
  88         kvno = ads_get_kvno(ctx->ads, r->account_name.string);
  89         blob = data_blob_const(r->ntpassword.hash, 16);
  90 
  91         status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx,
  92                                                      kvno,
  93                                                      r->account_name.string,
  94                                                      NULL,
  95                                                      ENCTYPE_ARCFOUR_HMAC,
  96                                                      blob);
  97         if (!NT_STATUS_IS_OK(status)) {
  98                 return status;
  99         }
 100 
 101         return NT_STATUS_OK;
 102 }
 103 
 104 /****************************************************************
 105 ****************************************************************/
 106 
 107 static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 108                             struct samsync_context *ctx,
 109                             enum netr_SamDatabaseID database_id,
 110                             uint64_t *sequence_num)
 111 {
 112         krb5_error_code ret = 0;
 113         NTSTATUS status;
 114         struct libnet_keytab_context *keytab_ctx = NULL;
 115         struct libnet_keytab_entry *entry;
 116         uint64_t old_sequence_num = 0;
 117         const char *principal = NULL;
 118 
 119         ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx);
 120         if (ret) {
 121                 return krb5_to_nt_status(ret);
 122         }
 123 
 124         keytab_ctx->clean_old_entries = ctx->clean_old_entries;
 125         ctx->private_data = keytab_ctx;
 126 
 127         status = keytab_ad_connect(mem_ctx,
 128                                    ctx->domain_name,
 129                                    ctx->username,
 130                                    ctx->password,
 131                                    keytab_ctx);
 132         if (!NT_STATUS_IS_OK(status)) {
 133                 TALLOC_FREE(keytab_ctx);
 134                 return status;
 135         }
 136 
 137         principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s",
 138                                     keytab_ctx->dns_domain_name);
 139         NT_STATUS_HAVE_NO_MEMORY(principal);
 140 
 141         entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL,
 142                                      mem_ctx);
 143         if (entry && (entry->password.length == 8)) {
 144                 old_sequence_num = BVAL(entry->password.data, 0);
 145         }
 146 
 147         if (sequence_num) {
 148                 *sequence_num = old_sequence_num;
 149         }
 150 
 151         return status;
 152 }
 153 
 154 /****************************************************************
 155 ****************************************************************/
 156 
 157 static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 158                                          enum netr_SamDatabaseID database_id,
 159                                          struct netr_DELTA_ENUM_ARRAY *r,
 160                                          uint64_t *sequence_num,
 161                                          struct samsync_context *ctx)
 162 {
 163         struct libnet_keytab_context *keytab_ctx =
 164                 (struct libnet_keytab_context *)ctx->private_data;
 165 
 166         NTSTATUS status = NT_STATUS_OK;
 167         int i;
 168 
 169         for (i = 0; i < r->num_deltas; i++) {
 170 
 171                 switch (r->delta_enum[i].delta_type) {
 172                 case NETR_DELTA_USER:
 173                         break;
 174                 case NETR_DELTA_DOMAIN:
 175                         if (sequence_num) {
 176                                 *sequence_num =
 177                                         r->delta_enum[i].delta_union.domain->sequence_num;
 178                         }
 179                         continue;
 180                 case NETR_DELTA_MODIFY_COUNT:
 181                         if (sequence_num) {
 182                                 *sequence_num =
 183                                         *r->delta_enum[i].delta_union.modified_count;
 184                         }
 185                         continue;
 186                 default:
 187                         continue;
 188                 }
 189 
 190                 status = fetch_sam_entry_keytab(mem_ctx, database_id,
 191                                                 r->delta_enum[i].delta_id_union.rid,
 192                                                 r->delta_enum[i].delta_union.user,
 193                                                 keytab_ctx);
 194                 if (!NT_STATUS_IS_OK(status)) {
 195                         goto out;
 196                 }
 197         }
 198  out:
 199         return status;
 200 }
 201 
 202 /****************************************************************
 203 ****************************************************************/
 204 
 205 static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 206                              struct samsync_context *ctx,
 207                              enum netr_SamDatabaseID database_id,
 208                              uint64_t sequence_num)
 209 {
 210         struct libnet_keytab_context *keytab_ctx =
 211                 (struct libnet_keytab_context *)ctx->private_data;
 212         krb5_error_code ret;
 213         NTSTATUS status;
 214         struct libnet_keytab_entry *entry;
 215         uint64_t old_sequence_num = 0;
 216         const char *principal = NULL;
 217 
 218         principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s",
 219                                     keytab_ctx->dns_domain_name);
 220         NT_STATUS_HAVE_NO_MEMORY(principal);
 221 
 222 
 223         entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL,
 224                                      mem_ctx);
 225         if (entry && (entry->password.length == 8)) {
 226                 old_sequence_num = BVAL(entry->password.data, 0);
 227         }
 228 
 229 
 230         if (sequence_num > old_sequence_num) {
 231                 DATA_BLOB blob;
 232                 blob = data_blob_talloc_zero(mem_ctx, 8);
 233                 SBVAL(blob.data, 0, sequence_num);
 234 
 235                 status = libnet_keytab_add_to_keytab_entries(mem_ctx, keytab_ctx,
 236                                                              0,
 237                                                              "SEQUENCE_NUM",
 238                                                              NULL,
 239                                                              ENCTYPE_NULL,
 240                                                              blob);
 241                 if (!NT_STATUS_IS_OK(status)) {
 242                         goto done;
 243                 }
 244         }
 245 
 246         ret = libnet_keytab_add(keytab_ctx);
 247         if (ret) {
 248                 status = krb5_to_nt_status(ret);
 249                 ctx->error_message = talloc_asprintf(ctx,
 250                         "Failed to add entries to keytab %s: %s",
 251                         keytab_ctx->keytab_name, error_message(ret));
 252                 TALLOC_FREE(keytab_ctx);
 253                 return status;
 254         }
 255 
 256         ctx->result_message = talloc_asprintf(ctx,
 257                 "Vampired %d accounts to keytab %s",
 258                 keytab_ctx->count,
 259                 keytab_ctx->keytab_name);
 260 
 261         status = NT_STATUS_OK;
 262 
 263  done:
 264         TALLOC_FREE(keytab_ctx);
 265 
 266         return status;
 267 }
 268 
 269 #else
 270 
 271 static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 272                             struct samsync_context *ctx,
 273                             enum netr_SamDatabaseID database_id,
 274                             uint64_t *sequence_num)
 275 {
 276         return NT_STATUS_NOT_SUPPORTED;
 277 }
 278 
 279 static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 280                                          enum netr_SamDatabaseID database_id,
 281                                          struct netr_DELTA_ENUM_ARRAY *r,
 282                                          uint64_t *sequence_num,
 283                                          struct samsync_context *ctx)
 284 {
 285         return NT_STATUS_NOT_SUPPORTED;
 286 }
 287 
 288 static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 289                              struct samsync_context *ctx,
 290                              enum netr_SamDatabaseID database_id,
 291                              uint64_t sequence_num)
 292 {
 293         return NT_STATUS_NOT_SUPPORTED;
 294 }
 295 
 296 #endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */
 297 
 298 const struct samsync_ops libnet_samsync_keytab_ops = {
 299         .startup                = init_keytab,
 300         .process_objects        = fetch_sam_entries_keytab,
 301         .finish                 = close_keytab
 302 };

/* [<][>][^][v][top][bottom][index][help] */