1668d11fc7f0b0e49a3a7a666a0dd7ea1a5eedd8
[samba.git] / source4 / kdc / mit_samba.c
1 /*
2    MIT-Samba4 library
3
4    Copyright (c) 2010, Simo Sorce <idra@samba.org>
5    Copyright (c) 2014-2015 Guenther Deschner <gd@samba.org>
6    Copyright (c) 2014-2016 Andreas Schneider <asn@samba.org>
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 #define TEVENT_DEPRECATED 1
23
24 #include "includes.h"
25 #include "param/param.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "system/kerberos.h"
28 #include <com_err.h>
29 #include <kdb.h>
30 #include <kadm5/kadm_err.h>
31 #include "kdc/sdb.h"
32 #include "kdc/sdb_kdb.h"
33 #include "auth/kerberos/kerberos.h"
34 #include "auth/kerberos/pac_utils.h"
35 #include "kdc/samba_kdc.h"
36 #include "kdc/pac-glue.h"
37 #include "kdc/db-glue.h"
38 #include "auth/auth.h"
39 #include "kdc/kpasswd_glue.h"
40 #include "auth/auth_sam.h"
41
42 #include "mit_samba.h"
43
44 #undef DBGC_CLASS
45 #define DBGC_CLASS DBGC_KERBEROS
46
47 void mit_samba_context_free(struct mit_samba_context *ctx)
48 {
49         /* free heimdal's krb5_context */
50         if (ctx->context) {
51                 krb5_free_context(ctx->context);
52         }
53
54         /* then free everything else */
55         talloc_free(ctx);
56 }
57
58 /*
59  * Implemant a callback to log to the MIT KDC log facility
60  *
61  * http://web.mit.edu/kerberos/krb5-devel/doc/plugindev/general.html#logging-from-kdc-and-kadmind-plugin-modules
62  */
63 static void mit_samba_debug(void *private_ptr, int msg_level, const char *msg)
64 {
65         int is_error = 1;
66
67         if (msg_level > 0) {
68                 is_error = 0;
69         }
70
71         com_err("", is_error, "%s", msg);
72 }
73
74 int mit_samba_context_init(struct mit_samba_context **_ctx)
75 {
76         NTSTATUS status;
77         struct mit_samba_context *ctx;
78         const char *s4_conf_file;
79         int ret;
80         struct samba_kdc_base_context base_ctx;
81
82         ctx = talloc_zero(NULL, struct mit_samba_context);
83         if (!ctx) {
84                 ret = ENOMEM;
85                 goto done;
86         }
87
88         base_ctx.ev_ctx = tevent_context_init(ctx);
89         if (!base_ctx.ev_ctx) {
90                 ret = ENOMEM;
91                 goto done;
92         }
93         tevent_loop_allow_nesting(base_ctx.ev_ctx);
94         base_ctx.lp_ctx = loadparm_init_global(false);
95         if (!base_ctx.lp_ctx) {
96                 ret = ENOMEM;
97                 goto done;
98         }
99
100         debug_set_callback(NULL, mit_samba_debug);
101
102         /* init s4 configuration */
103         s4_conf_file = lpcfg_configfile(base_ctx.lp_ctx);
104         if (s4_conf_file != NULL) {
105                 char *p = talloc_strdup(ctx, s4_conf_file);
106                 if (p == NULL) {
107                         ret = ENOMEM;
108                         goto done;
109                 }
110                 lpcfg_load(base_ctx.lp_ctx, p);
111                 TALLOC_FREE(p);
112         } else {
113                 lpcfg_load_default(base_ctx.lp_ctx);
114         }
115
116         status = samba_kdc_setup_db_ctx(ctx, &base_ctx, &ctx->db_ctx);
117         if (!NT_STATUS_IS_OK(status)) {
118                 ret = EINVAL;
119                 goto done;
120         }
121
122         /* init heimdal's krb_context and log facilities */
123         ret = smb_krb5_init_context_basic(ctx,
124                                           ctx->db_ctx->lp_ctx,
125                                           &ctx->context);
126         if (ret) {
127                 goto done;
128         }
129
130         ret = 0;
131
132 done:
133         if (ret) {
134                 mit_samba_context_free(ctx);
135         } else {
136                 *_ctx = ctx;
137         }
138         return ret;
139 }
140
141 static krb5_error_code ks_is_tgs_principal(struct mit_samba_context *ctx,
142                                            krb5_const_principal principal)
143 {
144         char *p;
145         int eq = -1;
146
147         p = smb_krb5_principal_get_comp_string(ctx, ctx->context, principal, 0);
148
149         eq = krb5_princ_size(ctx->context, principal) == 2 &&
150              (strcmp(p, KRB5_TGS_NAME) == 0);
151
152         talloc_free(p);
153
154         return eq;
155 }
156
157 int mit_samba_generate_salt(krb5_data *salt)
158 {
159         if (salt == NULL) {
160                 return EINVAL;
161         }
162
163         salt->length = 16;
164         salt->data = malloc(salt->length);
165         if (salt->data == NULL) {
166                 return ENOMEM;
167         }
168
169         generate_random_buffer((uint8_t *)salt->data, salt->length);
170
171         return 0;
172 }
173
174 int mit_samba_generate_random_password(krb5_data *pwd)
175 {
176         TALLOC_CTX *tmp_ctx;
177         char *password;
178
179         if (pwd == NULL) {
180                 return EINVAL;
181         }
182         pwd->length = 24;
183
184         tmp_ctx = talloc_named(NULL,
185                                0,
186                                "mit_samba_create_principal_password context");
187         if (tmp_ctx == NULL) {
188                 return ENOMEM;
189         }
190
191         password = generate_random_password(tmp_ctx, pwd->length, pwd->length);
192         if (password == NULL) {
193                 talloc_free(tmp_ctx);
194                 return ENOMEM;
195         }
196
197         pwd->data = strdup(password);
198         talloc_free(tmp_ctx);
199         if (pwd->data == NULL) {
200                 return ENOMEM;
201         }
202
203         return 0;
204 }
205
206 int mit_samba_get_principal(struct mit_samba_context *ctx,
207                             krb5_const_principal principal,
208                             unsigned int kflags,
209                             krb5_db_entry **_kentry)
210 {
211         struct sdb_entry_ex sentry = {
212                 .free_entry = NULL,
213         };
214         krb5_db_entry *kentry;
215         int ret;
216         int sflags = 0;
217         krb5_principal referral_principal = NULL;
218
219         kentry = calloc(1, sizeof(krb5_db_entry));
220         if (kentry == NULL) {
221                 return ENOMEM;
222         }
223
224         if (kflags & KRB5_KDB_FLAG_CANONICALIZE) {
225                 sflags |= SDB_F_CANON;
226         }
227         if (kflags & (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY |
228                       KRB5_KDB_FLAG_INCLUDE_PAC)) {
229                 /*
230                  * KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY is equal to
231                  * SDB_F_FOR_AS_REQ
232                  *
233                  * We use ANY to also allow AS_REQ for service principal names
234                  * This is supported by Windows.
235                  */
236                 sflags |= SDB_F_GET_ANY|SDB_F_FOR_AS_REQ;
237         } else if (ks_is_tgs_principal(ctx, principal)) {
238                 sflags |= SDB_F_GET_KRBTGT;
239         } else {
240                 sflags |= SDB_F_GET_SERVER|SDB_F_FOR_TGS_REQ;
241         }
242
243         /* always set this or the created_by data will not be populated by samba's
244          * backend and we will fail to parse the entry later */
245         sflags |= SDB_F_ADMIN_DATA;
246
247
248 fetch_referral_principal:
249         ret = samba_kdc_fetch(ctx->context, ctx->db_ctx,
250                               principal, sflags, 0, &sentry);
251         switch (ret) {
252         case 0:
253                 break;
254         case SDB_ERR_NOENTRY:
255                 ret = KRB5_KDB_NOENTRY;
256                 goto done;
257         case SDB_ERR_WRONG_REALM: {
258                 char *dest_realm = NULL;
259                 const char *our_realm = lpcfg_realm(ctx->db_ctx->lp_ctx);
260
261                 if (sflags & SDB_F_FOR_AS_REQ) {
262                         /*
263                          * If this is a request for a TGT, we are done. The KDC
264                          * will return the correct error to the client.
265                          */
266                         ret = 0;
267                         break;
268                 }
269
270                 if (referral_principal != NULL) {
271                         sdb_free_entry(&sentry);
272                         ret = KRB5_KDB_NOENTRY;
273                         goto done;
274                 }
275
276                 /*
277                  * We get a TGS request
278                  *
279                  *     cifs/dc7.SAMBA2008R2.EXAMPLE.COM@ADDOM.SAMBA.EXAMPLE.COM
280                  *
281                  * to our DC for the realm
282                  *
283                  *     ADDOM.SAMBA.EXAMPLE.COM
284                  *
285                  * We look up if we have and entry in the database and get an
286                  * entry with the pricipal:
287                  *
288                  *     cifs/dc7.SAMBA2008R2.EXAMPLE.COM@SAMBA2008R2.EXAMPLE.COM
289                  *
290                  * and the error: SDB_ERR_WRONG_REALM.
291                  *
292                  * In the case of a TGS-REQ we need to return a referral ticket
293                  * fo the next trust hop to the client. This ticket will have
294                  * the following principal:
295                  *
296                  *     krbtgt/SAMBA2008R2.EXAMPLE.COM@ADDOM.SAMBA.EXAMPLE.COM
297                  *
298                  * We just redo the lookup in the database with the referral
299                  * principal and return success.
300                  */
301                 dest_realm = smb_krb5_principal_get_realm(
302                         ctx, ctx->context, sentry.entry.principal);
303                 sdb_free_entry(&sentry);
304                 if (dest_realm == NULL) {
305                         ret = KRB5_KDB_NOENTRY;
306                         goto done;
307                 }
308
309                 ret = smb_krb5_make_principal(ctx->context,
310                                               &referral_principal,
311                                               our_realm,
312                                               KRB5_TGS_NAME,
313                                               dest_realm,
314                                               NULL);
315                 TALLOC_FREE(dest_realm);
316                 if (ret != 0) {
317                         goto done;
318                 }
319
320                 principal = referral_principal;
321                 goto fetch_referral_principal;
322         }
323         case SDB_ERR_NOT_FOUND_HERE:
324                 /* FIXME: RODC support */
325         default:
326                 goto done;
327         }
328
329         ret = sdb_entry_ex_to_kdb_entry_ex(ctx->context, &sentry, kentry);
330
331         sdb_free_entry(&sentry);
332
333 done:
334         krb5_free_principal(ctx->context, referral_principal);
335         referral_principal = NULL;
336
337         if (ret) {
338                 free(kentry);
339         } else {
340                 *_kentry = kentry;
341         }
342         return ret;
343 }
344
345 int mit_samba_get_firstkey(struct mit_samba_context *ctx,
346                            krb5_db_entry **_kentry)
347 {
348         struct sdb_entry_ex sentry = {
349                 .free_entry = NULL,
350         };
351         krb5_db_entry *kentry;
352         int ret;
353
354         kentry = malloc(sizeof(krb5_db_entry));
355         if (kentry == NULL) {
356                 return ENOMEM;
357         }
358
359         ret = samba_kdc_firstkey(ctx->context, ctx->db_ctx, &sentry);
360         switch (ret) {
361         case 0:
362                 break;
363         case SDB_ERR_NOENTRY:
364                 free(kentry);
365                 return KRB5_KDB_NOENTRY;
366         case SDB_ERR_NOT_FOUND_HERE:
367                 /* FIXME: RODC support */
368         default:
369                 free(kentry);
370                 return ret;
371         }
372
373         ret = sdb_entry_ex_to_kdb_entry_ex(ctx->context, &sentry, kentry);
374
375         sdb_free_entry(&sentry);
376
377         if (ret) {
378                 free(kentry);
379         } else {
380                 *_kentry = kentry;
381         }
382         return ret;
383 }
384
385 int mit_samba_get_nextkey(struct mit_samba_context *ctx,
386                           krb5_db_entry **_kentry)
387 {
388         struct sdb_entry_ex sentry = {
389                 .free_entry = NULL,
390         };
391         krb5_db_entry *kentry;
392         int ret;
393
394         kentry = malloc(sizeof(krb5_db_entry));
395         if (kentry == NULL) {
396                 return ENOMEM;
397         }
398
399         ret = samba_kdc_nextkey(ctx->context, ctx->db_ctx, &sentry);
400         switch (ret) {
401         case 0:
402                 break;
403         case SDB_ERR_NOENTRY:
404                 free(kentry);
405                 return KRB5_KDB_NOENTRY;
406         case SDB_ERR_NOT_FOUND_HERE:
407                 /* FIXME: RODC support */
408         default:
409                 free(kentry);
410                 return ret;
411         }
412
413         ret = sdb_entry_ex_to_kdb_entry_ex(ctx->context, &sentry, kentry);
414
415         sdb_free_entry(&sentry);
416
417         if (ret) {
418                 free(kentry);
419         } else {
420                 *_kentry = kentry;
421         }
422         return ret;
423 }
424
425 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
426                       krb5_context context,
427                       krb5_db_entry *client,
428                       krb5_keyblock *client_key,
429                       krb5_pac *pac)
430 {
431         TALLOC_CTX *tmp_ctx;
432         DATA_BLOB *logon_info_blob = NULL;
433         DATA_BLOB *upn_dns_info_blob = NULL;
434         DATA_BLOB *cred_ndr = NULL;
435         DATA_BLOB **cred_ndr_ptr = NULL;
436         DATA_BLOB cred_blob = data_blob_null;
437         DATA_BLOB *pcred_blob = NULL;
438         NTSTATUS nt_status;
439         krb5_error_code code;
440         struct samba_kdc_entry *skdc_entry;
441
442         skdc_entry = talloc_get_type_abort(client->e_data,
443                                            struct samba_kdc_entry);
444
445         tmp_ctx = talloc_named(smb_ctx,
446                                0,
447                                "mit_samba_get_pac_data_blobs context");
448         if (tmp_ctx == NULL) {
449                 return ENOMEM;
450         }
451
452 #if 0 /* TODO Find out if this is a pkinit_reply key */
453         /* Check if we have a PREAUTH key */
454         if (client_key != NULL) {
455                 cred_ndr_ptr = &cred_ndr;
456         }
457 #endif
458
459         nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
460                                             skdc_entry,
461                                             &logon_info_blob,
462                                             cred_ndr_ptr,
463                                             &upn_dns_info_blob,
464                                             NULL, NULL);
465         if (!NT_STATUS_IS_OK(nt_status)) {
466                 talloc_free(tmp_ctx);
467                 if (NT_STATUS_EQUAL(nt_status,
468                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
469                         return ENOENT;
470                 }
471                 return EINVAL;
472         }
473
474         if (cred_ndr != NULL) {
475                 code = samba_kdc_encrypt_pac_credentials(context,
476                                                          client_key,
477                                                          cred_ndr,
478                                                          tmp_ctx,
479                                                          &cred_blob);
480                 if (code != 0) {
481                         talloc_free(tmp_ctx);
482                         return code;
483                 }
484                 pcred_blob = &cred_blob;
485         }
486
487         code = samba_make_krb5_pac(context,
488                                    logon_info_blob,
489                                    pcred_blob,
490                                    upn_dns_info_blob,
491                                    NULL,
492                                    NULL,
493                                    pac);
494
495         talloc_free(tmp_ctx);
496         return code;
497 }
498
499 krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
500                                     krb5_context context,
501                                     int flags,
502                                     krb5_const_principal client_principal,
503                                     krb5_db_entry *client,
504                                     krb5_db_entry *server,
505                                     krb5_db_entry *krbtgt,
506                                     krb5_keyblock *krbtgt_keyblock,
507                                     krb5_pac *pac)
508 {
509         TALLOC_CTX *tmp_ctx;
510         krb5_error_code code;
511         NTSTATUS nt_status;
512         DATA_BLOB *pac_blob = NULL;
513         DATA_BLOB *upn_blob = NULL;
514         DATA_BLOB *deleg_blob = NULL;
515         struct samba_kdc_entry *client_skdc_entry = NULL;
516         struct samba_kdc_entry *krbtgt_skdc_entry = NULL;
517         struct samba_kdc_entry *server_skdc_entry = NULL;
518         bool is_in_db = false;
519         bool is_untrusted = false;
520         size_t num_types = 0;
521         uint32_t *types = NULL;
522         uint32_t forced_next_type = 0;
523         size_t i = 0;
524         ssize_t logon_info_idx = -1;
525         ssize_t delegation_idx = -1;
526         ssize_t logon_name_idx = -1;
527         ssize_t upn_dns_info_idx = -1;
528         ssize_t srv_checksum_idx = -1;
529         ssize_t kdc_checksum_idx = -1;
530         krb5_pac new_pac = NULL;
531         bool ok;
532
533         /* Create a memory context early so code can use talloc_stackframe() */
534         tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context");
535         if (tmp_ctx == NULL) {
536                 return ENOMEM;
537         }
538
539         if (client != NULL) {
540                 client_skdc_entry =
541                         talloc_get_type_abort(client->e_data,
542                                               struct samba_kdc_entry);
543
544                 /*
545                  * Check the objectSID of the client and pac data are the same.
546                  * Does a parse and SID check, but no crypto.
547                  */
548                 code = samba_kdc_validate_pac_blob(context, client_skdc_entry, *pac);
549                 if (code != 0) {
550                         goto done;
551                 }
552         }
553
554         if (server == NULL) {
555                 code = EINVAL;
556                 goto done;
557         }
558
559         server_skdc_entry =
560                 talloc_get_type_abort(server->e_data,
561                                       struct samba_kdc_entry);
562
563         /* The account may be set not to want the PAC */
564         ok = samba_princ_needs_pac(server_skdc_entry);
565         if (!ok) {
566                 code = EINVAL;
567                 goto done;
568         }
569
570         if (krbtgt == NULL) {
571                 code = EINVAL;
572                 goto done;
573         }
574         krbtgt_skdc_entry =
575                 talloc_get_type_abort(krbtgt->e_data,
576                                       struct samba_kdc_entry);
577
578         code = samba_krbtgt_is_in_db(krbtgt_skdc_entry,
579                                      &is_in_db,
580                                      &is_untrusted);
581         if (code != 0) {
582                 goto done;
583         }
584
585         if (is_untrusted) {
586                 if (client == NULL) {
587                         code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
588                         goto done;
589                 }
590
591                 nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
592                                                     client_skdc_entry,
593                                                     &pac_blob,
594                                                     NULL,
595                                                     &upn_blob,
596                                                     NULL, NULL);
597                 if (!NT_STATUS_IS_OK(nt_status)) {
598                         code = EINVAL;
599                         goto done;
600                 }
601         } else {
602                 struct PAC_SIGNATURE_DATA *pac_srv_sig;
603                 struct PAC_SIGNATURE_DATA *pac_kdc_sig;
604
605                 pac_blob = talloc_zero(tmp_ctx, DATA_BLOB);
606                 if (pac_blob == NULL) {
607                         code = ENOMEM;
608                         goto done;
609                 }
610
611                 pac_srv_sig = talloc_zero(tmp_ctx, struct PAC_SIGNATURE_DATA);
612                 if (pac_srv_sig == NULL) {
613                         code = ENOMEM;
614                         goto done;
615                 }
616
617                 pac_kdc_sig = talloc_zero(tmp_ctx, struct PAC_SIGNATURE_DATA);
618                 if (pac_kdc_sig == NULL) {
619                         code = ENOMEM;
620                         goto done;
621                 }
622
623                 nt_status = samba_kdc_update_pac_blob(tmp_ctx,
624                                                       context,
625                                                       krbtgt_skdc_entry->kdc_db_ctx->samdb,
626                                                       *pac,
627                                                       pac_blob,
628                                                       pac_srv_sig,
629                                                       pac_kdc_sig);
630                 if (!NT_STATUS_IS_OK(nt_status)) {
631                         DEBUG(0, ("Update PAC blob failed: %s\n",
632                                   nt_errstr(nt_status)));
633                         code = EINVAL;
634                         goto done;
635                 }
636
637                 if (is_in_db) {
638                         /*
639                          * Now check the KDC signature, fetching the correct
640                          * key based on the enc type.
641                          */
642                         code = check_pac_checksum(pac_srv_sig->signature,
643                                                   pac_kdc_sig,
644                                                   context,
645                                                   krbtgt_keyblock);
646                         if (code != 0) {
647                                 DBG_INFO("PAC KDC signature failed to verify\n");
648                                 goto done;
649                         }
650                 }
651         }
652
653         if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
654                 deleg_blob = talloc_zero(tmp_ctx, DATA_BLOB);
655                 if (deleg_blob == NULL) {
656                         code = ENOMEM;
657                         goto done;
658                 }
659
660                 nt_status = samba_kdc_update_delegation_info_blob(tmp_ctx,
661                                                                   context,
662                                                                   *pac,
663                                                                   server->princ,
664                                                                   discard_const(client_principal),
665                                                                   deleg_blob);
666                 if (!NT_STATUS_IS_OK(nt_status)) {
667                         DEBUG(0, ("Update delegation info failed: %s\n",
668                                   nt_errstr(nt_status)));
669                         code = EINVAL;
670                         goto done;
671                 }
672         }
673
674         /* Check the types of the given PAC */
675         code = krb5_pac_get_types(context, *pac, &num_types, &types);
676         if (code != 0) {
677                 goto done;
678         }
679
680         for (i = 0; i < num_types; i++) {
681                 switch (types[i]) {
682                 case PAC_TYPE_LOGON_INFO:
683                         if (logon_info_idx != -1) {
684                                 DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
685                                             types[i],
686                                             logon_info_idx,
687                                             i);
688                                 SAFE_FREE(types);
689                                 code = EINVAL;
690                                 goto done;
691                         }
692                         logon_info_idx = i;
693                         break;
694                 case PAC_TYPE_CONSTRAINED_DELEGATION:
695                         if (delegation_idx != -1) {
696                                 DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
697                                             types[i],
698                                             delegation_idx,
699                                             i);
700                                 SAFE_FREE(types);
701                                 code = EINVAL;
702                                 goto done;
703                         }
704                         delegation_idx = i;
705                         break;
706                 case PAC_TYPE_LOGON_NAME:
707                         if (logon_name_idx != -1) {
708                                 DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
709                                             types[i],
710                                             logon_name_idx,
711                                             i);
712                                 SAFE_FREE(types);
713                                 code = EINVAL;
714                                 goto done;
715                         }
716                         logon_name_idx = i;
717                         break;
718                 case PAC_TYPE_UPN_DNS_INFO:
719                         if (upn_dns_info_idx != -1) {
720                                 DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
721                                             types[i],
722                                             upn_dns_info_idx,
723                                             i);
724                                 SAFE_FREE(types);
725                                 code = EINVAL;
726                                 goto done;
727                         }
728                         upn_dns_info_idx = i;
729                         break;
730                 case PAC_TYPE_SRV_CHECKSUM:
731                         if (srv_checksum_idx != -1) {
732                                 DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
733                                             types[i],
734                                             srv_checksum_idx,
735                                             i);
736                                 SAFE_FREE(types);
737                                 code = EINVAL;
738                                 goto done;
739                         }
740                         srv_checksum_idx = i;
741                         break;
742                 case PAC_TYPE_KDC_CHECKSUM:
743                         if (kdc_checksum_idx != -1) {
744                                 DBG_WARNING("logon type[%u] twice [%zd] and [%zu]: \n",
745                                             types[i],
746                                             kdc_checksum_idx,
747                                             i);
748                                 SAFE_FREE(types);
749                                 code = EINVAL;
750                                 goto done;
751                         }
752                         kdc_checksum_idx = i;
753                         break;
754                 default:
755                         continue;
756                 }
757         }
758
759         if (logon_info_idx == -1) {
760                 DEBUG(1, ("PAC_TYPE_LOGON_INFO missing\n"));
761                 SAFE_FREE(types);
762                 code = EINVAL;
763                 goto done;
764         }
765         if (logon_name_idx == -1) {
766                 DEBUG(1, ("PAC_TYPE_LOGON_NAME missing\n"));
767                 SAFE_FREE(types);
768                 code = EINVAL;
769                 goto done;
770         }
771         if (srv_checksum_idx == -1) {
772                 DEBUG(1, ("PAC_TYPE_SRV_CHECKSUM missing\n"));
773                 SAFE_FREE(types);
774                 code = EINVAL;
775                 goto done;
776         }
777         if (kdc_checksum_idx == -1) {
778                 DEBUG(1, ("PAC_TYPE_KDC_CHECKSUM missing\n"));
779                 SAFE_FREE(types);
780                 code = EINVAL;
781                 goto done;
782         }
783
784         /* Build an updated PAC */
785         code = krb5_pac_init(context, &new_pac);
786         if (code != 0) {
787                 SAFE_FREE(types);
788                 goto done;
789         }
790
791         for (i = 0;;) {
792                 krb5_data type_data;
793                 DATA_BLOB type_blob = data_blob_null;
794                 uint32_t type;
795
796                 if (forced_next_type != 0) {
797                         /*
798                          * We need to inject possible missing types
799                          */
800                         type = forced_next_type;
801                         forced_next_type = 0;
802                 } else if (i < num_types) {
803                         type = types[i];
804                         i++;
805                 } else {
806                         break;
807                 }
808
809                 switch (type) {
810                 case PAC_TYPE_LOGON_INFO:
811                         type_blob = *pac_blob;
812
813                         if (delegation_idx == -1 && deleg_blob != NULL) {
814                                 /* inject CONSTRAINED_DELEGATION behind */
815                                 forced_next_type = PAC_TYPE_CONSTRAINED_DELEGATION;
816                         }
817                         break;
818                 case PAC_TYPE_CONSTRAINED_DELEGATION:
819                         if (deleg_blob != NULL) {
820                                 type_blob = *deleg_blob;
821                         }
822                         break;
823                 case PAC_TYPE_CREDENTIAL_INFO:
824                         /*
825                          * Note that we copy the credential blob,
826                          * as it's only usable with the PKINIT based
827                          * AS-REP reply key, it's only available on the
828                          * host which did the AS-REQ/AS-REP exchange.
829                          *
830                          * This matches Windows 2008R2...
831                          */
832                         break;
833                 case PAC_TYPE_LOGON_NAME:
834                         /*
835                          * This is generated in the main KDC code
836                          */
837                         continue;
838                 case PAC_TYPE_UPN_DNS_INFO:
839                         /*
840                          * Replace in the RODC case, otherwise
841                          * upn_blob is NULL and we just copy.
842                          */
843                         if (upn_blob != NULL) {
844                                 type_blob = *upn_blob;
845                         }
846                         break;
847                 case PAC_TYPE_SRV_CHECKSUM:
848                         /*
849                          * This is generated in the main KDC code
850                          */
851                         continue;
852                 case PAC_TYPE_KDC_CHECKSUM:
853                         /*
854                          * This is generated in the main KDC code
855                          */
856                         continue;
857                 default:
858                         /* just copy... */
859                         break;
860                 }
861
862                 if (type_blob.length != 0) {
863                         code = smb_krb5_copy_data_contents(&type_data,
864                                                            type_blob.data,
865                                                            type_blob.length);
866                         if (code != 0) {
867                                 SAFE_FREE(types);
868                                 krb5_pac_free(context, new_pac);
869                                 goto done;
870                         }
871                 } else {
872                         code = krb5_pac_get_buffer(context,
873                                                    *pac,
874                                                    type,
875                                                    &type_data);
876                         if (code != 0) {
877                                 SAFE_FREE(types);
878                                 krb5_pac_free(context, new_pac);
879                                 goto done;
880                         }
881                 }
882
883                 code = krb5_pac_add_buffer(context,
884                                            new_pac,
885                                            type,
886                                            &type_data);
887                 smb_krb5_free_data_contents(context, &type_data);
888                 if (code != 0) {
889                         SAFE_FREE(types);
890                         krb5_pac_free(context, new_pac);
891                         goto done;
892                 }
893         }
894
895         SAFE_FREE(types);
896
897         /* We now replace the pac */
898         krb5_pac_free(context, *pac);
899         *pac = new_pac;
900 done:
901         talloc_free(tmp_ctx);
902         return code;
903 }
904
905 /* provide header, function is exported but there are no public headers */
906
907 krb5_error_code encode_krb5_padata_sequence(krb5_pa_data *const *rep, krb5_data **code);
908
909 /* this function allocates 'data' using malloc.
910  * The caller is responsible for freeing it */
911 static void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data)
912 {
913         krb5_error_code ret = 0;
914         krb5_pa_data pa, *ppa[2];
915         krb5_data *d = NULL;
916
917         if (!e_data)
918                 return;
919
920         e_data->data   = NULL;
921         e_data->length = 0;
922
923         pa.magic                = KV5M_PA_DATA;
924         pa.pa_type              = KRB5_PADATA_PW_SALT;
925         pa.length               = 12;
926         pa.contents             = malloc(pa.length);
927         if (!pa.contents) {
928                 return;
929         }
930
931         SIVAL(pa.contents, 0, NT_STATUS_V(nt_status));
932         SIVAL(pa.contents, 4, 0);
933         SIVAL(pa.contents, 8, 1);
934
935         ppa[0] = &pa;
936         ppa[1] = NULL;
937
938         ret = encode_krb5_padata_sequence(ppa, &d);
939         free(pa.contents);
940         if (ret) {
941                 return;
942         }
943
944         e_data->data   = (uint8_t *)d->data;
945         e_data->length = d->length;
946
947         /* free d, not d->data - gd */
948         free(d);
949
950         return;
951 }
952
953 int mit_samba_check_client_access(struct mit_samba_context *ctx,
954                                   krb5_db_entry *client,
955                                   const char *client_name,
956                                   krb5_db_entry *server,
957                                   const char *server_name,
958                                   const char *netbios_name,
959                                   bool password_change,
960                                   DATA_BLOB *e_data)
961 {
962         struct samba_kdc_entry *skdc_entry;
963         NTSTATUS nt_status;
964
965         skdc_entry = talloc_get_type(client->e_data, struct samba_kdc_entry);
966
967         nt_status = samba_kdc_check_client_access(skdc_entry,
968                                                   client_name,
969                                                   netbios_name,
970                                                   password_change);
971
972         if (!NT_STATUS_IS_OK(nt_status)) {
973                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) {
974                         return ENOMEM;
975                 }
976
977                 samba_kdc_build_edata_reply(nt_status, e_data);
978
979                 return samba_kdc_map_policy_err(nt_status);
980         }
981
982         return 0;
983 }
984
985 int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
986                               krb5_db_entry *kentry,
987                               const char *target_name,
988                               bool is_nt_enterprise_name)
989 {
990 #if 1
991         /*
992          * This is disabled because mit_samba_update_pac_data() does not handle
993          * S4U_DELEGATION_INFO
994          */
995
996         return KRB5KDC_ERR_BADOPTION;
997 #else
998         krb5_principal target_principal;
999         int flags = 0;
1000         int ret;
1001
1002         if (is_nt_enterprise_name) {
1003                 flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE;
1004         }
1005
1006         ret = krb5_parse_name_flags(ctx->context, target_name,
1007                                     flags, &target_principal);
1008         if (ret) {
1009                 return ret;
1010         }
1011
1012         ret = samba_kdc_check_s4u2proxy(ctx->context,
1013                                         ctx->db_ctx,
1014                                         skdc_entry,
1015                                         target_principal);
1016
1017         krb5_free_principal(ctx->context, target_principal);
1018
1019         return ret;
1020 #endif
1021 }
1022
1023 static krb5_error_code mit_samba_change_pwd_error(krb5_context context,
1024                                                   NTSTATUS result,
1025                                                   enum samPwdChangeReason reject_reason,
1026                                                   struct samr_DomInfo1 *dominfo)
1027 {
1028         krb5_error_code code = KADM5_PASS_Q_GENERIC;
1029
1030         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
1031                 code = KADM5_BAD_PRINCIPAL;
1032                 krb5_set_error_message(context,
1033                                        code,
1034                                        "No such user when changing password");
1035         }
1036         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
1037                 code = KADM5_PASS_Q_GENERIC;
1038                 krb5_set_error_message(context,
1039                                        code,
1040                                        "Not permitted to change password");
1041         }
1042         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) &&
1043             dominfo != NULL) {
1044                 switch (reject_reason) {
1045                 case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT:
1046                         code = KADM5_PASS_Q_TOOSHORT;
1047                         krb5_set_error_message(context,
1048                                                code,
1049                                                "Password too short, password "
1050                                                "must be at least %d characters "
1051                                                "long.",
1052                                                dominfo->min_password_length);
1053                         break;
1054                 case SAM_PWD_CHANGE_NOT_COMPLEX:
1055                         code = KADM5_PASS_Q_DICT;
1056                         krb5_set_error_message(context,
1057                                                code,
1058                                                "Password does not meet "
1059                                                "complexity requirements");
1060                         break;
1061                 case SAM_PWD_CHANGE_PWD_IN_HISTORY:
1062                         code = KADM5_PASS_TOOSOON;
1063                         krb5_set_error_message(context,
1064                                                code,
1065                                                "Password is already in password "
1066                                                "history. New password must not "
1067                                                "match any of your %d previous "
1068                                                "passwords.",
1069                                                dominfo->password_history_length);
1070                         break;
1071                 default:
1072                         code = KADM5_PASS_Q_GENERIC;
1073                         krb5_set_error_message(context,
1074                                                code,
1075                                                "Password change rejected, "
1076                                                "password changes may not be "
1077                                                "permitted on this account, or "
1078                                                "the minimum password age may "
1079                                                "not have elapsed.");
1080                         break;
1081                 }
1082         }
1083
1084         return code;
1085 }
1086
1087 int mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
1088                                       char *pwd,
1089                                       krb5_db_entry *db_entry)
1090 {
1091         NTSTATUS status;
1092         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1093         TALLOC_CTX *tmp_ctx;
1094         DATA_BLOB password;
1095         enum samPwdChangeReason reject_reason;
1096         struct samr_DomInfo1 *dominfo;
1097         const char *error_string = NULL;
1098         struct auth_user_info_dc *user_info_dc;
1099         struct samba_kdc_entry *p =
1100                 talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
1101         krb5_error_code code = 0;
1102
1103 #ifdef DEBUG_PASSWORD
1104         DEBUG(1,("mit_samba_kpasswd_change_password called with: %s\n", pwd));
1105 #endif
1106
1107         tmp_ctx = talloc_named(ctx, 0, "mit_samba_kpasswd_change_password");
1108         if (tmp_ctx == NULL) {
1109                 return ENOMEM;
1110         }
1111
1112         status = authsam_make_user_info_dc(tmp_ctx,
1113                                            ctx->db_ctx->samdb,
1114                                            lpcfg_netbios_name(ctx->db_ctx->lp_ctx),
1115                                            lpcfg_sam_name(ctx->db_ctx->lp_ctx),
1116                                            lpcfg_sam_dnsname(ctx->db_ctx->lp_ctx),
1117                                            p->realm_dn,
1118                                            p->msg,
1119                                            data_blob(NULL, 0),
1120                                            data_blob(NULL, 0),
1121                                            &user_info_dc);
1122         if (!NT_STATUS_IS_OK(status)) {
1123                 DEBUG(1,("authsam_make_user_info_dc failed: %s\n",
1124                         nt_errstr(status)));
1125                 talloc_free(tmp_ctx);
1126                 return EINVAL;
1127         }
1128
1129         status = auth_generate_session_info(tmp_ctx,
1130                                             ctx->db_ctx->lp_ctx,
1131                                             ctx->db_ctx->samdb,
1132                                             user_info_dc,
1133                                             0, /* session_info_flags */
1134                                             &ctx->session_info);
1135
1136         if (!NT_STATUS_IS_OK(status)) {
1137                 DEBUG(1,("auth_generate_session_info failed: %s\n",
1138                         nt_errstr(status)));
1139                 talloc_free(tmp_ctx);
1140                 return EINVAL;
1141         }
1142
1143         /* password is expected as UTF16 */
1144
1145         if (!convert_string_talloc(tmp_ctx, CH_UTF8, CH_UTF16,
1146                                    pwd, strlen(pwd),
1147                                    &password.data, &password.length)) {
1148                 DEBUG(1,("convert_string_talloc failed\n"));
1149                 talloc_free(tmp_ctx);
1150                 return EINVAL;
1151         }
1152
1153         status = samdb_kpasswd_change_password(tmp_ctx,
1154                                                ctx->db_ctx->lp_ctx,
1155                                                ctx->db_ctx->ev_ctx,
1156                                                ctx->db_ctx->samdb,
1157                                                ctx->session_info,
1158                                                &password,
1159                                                &reject_reason,
1160                                                &dominfo,
1161                                                &error_string,
1162                                                &result);
1163         if (!NT_STATUS_IS_OK(status)) {
1164                 DEBUG(1,("samdb_kpasswd_change_password failed: %s\n",
1165                         nt_errstr(status)));
1166                 code = KADM5_PASS_Q_GENERIC;
1167                 krb5_set_error_message(ctx->context, code, "%s", error_string);
1168                 goto out;
1169         }
1170
1171         if (!NT_STATUS_IS_OK(result)) {
1172                 code = mit_samba_change_pwd_error(ctx->context,
1173                                                   result,
1174                                                   reject_reason,
1175                                                   dominfo);
1176         }
1177
1178 out:
1179         talloc_free(tmp_ctx);
1180
1181         return code;
1182 }
1183
1184 void mit_samba_zero_bad_password_count(krb5_db_entry *db_entry)
1185 {
1186         struct netr_SendToSamBase *send_to_sam = NULL;
1187         struct samba_kdc_entry *p =
1188                 talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
1189         struct ldb_dn *domain_dn;
1190
1191         domain_dn = ldb_get_default_basedn(p->kdc_db_ctx->samdb);
1192
1193         authsam_logon_success_accounting(p->kdc_db_ctx->samdb,
1194                                          p->msg,
1195                                          domain_dn,
1196                                          true,
1197                                          &send_to_sam);
1198         /* TODO: RODC support */
1199 }
1200
1201
1202 void mit_samba_update_bad_password_count(krb5_db_entry *db_entry)
1203 {
1204         struct samba_kdc_entry *p =
1205                 talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
1206
1207         authsam_update_bad_pwd_count(p->kdc_db_ctx->samdb,
1208                                      p->msg,
1209                                      ldb_get_default_basedn(p->kdc_db_ctx->samdb));
1210 }
1211
1212 bool mit_samba_princ_needs_pac(krb5_db_entry *db_entry)
1213 {
1214         struct samba_kdc_entry *skdc_entry =
1215                 talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
1216
1217         return samba_princ_needs_pac(skdc_entry);
1218 }