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