s4-auth-krb: Move keytab functions in a separate file.
[kai/samba-autobuild/.git] / source4 / auth / kerberos / srv_keytab.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Kerberos utility functions
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
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
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23
24 #include "includes.h"
25 #include "auth/credentials/credentials.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "auth/kerberos/kerberos_srv_keytab.h"
29 #include "auth/kerberos/kerberos_util.h"
30 #include <ldb.h>
31 #include "param/secrets.h"
32
33 static krb5_error_code principals_from_msg(TALLOC_CTX *parent_ctx,
34                         struct ldb_message *msg,
35                         struct smb_krb5_context *smb_krb5_context,
36                         struct principal_container ***principals_out,
37                         const char **error_string)
38 {
39         unsigned int i;
40         krb5_error_code ret;
41         char *upper_realm;
42         const char *realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
43         const char *samAccountName = ldb_msg_find_attr_as_string(msg,
44                                                 "samAccountName", NULL);
45         struct ldb_message_element *spn_el = ldb_msg_find_element(msg,
46                                                 "servicePrincipalName");
47         TALLOC_CTX *tmp_ctx;
48         struct principal_container **principals;
49         tmp_ctx = talloc_new(parent_ctx);
50         if (!tmp_ctx) {
51                 *error_string = "Cannot allocate tmp_ctx";
52                 return ENOMEM;
53         }
54
55         if (!realm) {
56                 *error_string = "Cannot have a kerberos secret in "
57                                 "secrets.ldb without a realm";
58                 return EINVAL;
59         }
60
61         upper_realm = strupper_talloc(tmp_ctx, realm);
62         if (!upper_realm) {
63                 talloc_free(tmp_ctx);
64                 *error_string = "Cannot allocate full upper case realm";
65                 return ENOMEM;
66         }
67
68         principals = talloc_array(tmp_ctx, struct principal_container *,
69                                   spn_el ? (spn_el->num_values + 2) : 2);
70
71         spn_el = ldb_msg_find_element(msg, "servicePrincipalName");
72         for (i=0; spn_el && i < spn_el->num_values; i++) {
73                 principals[i] = talloc(principals, struct principal_container);
74                 if (!principals[i]) {
75                         talloc_free(tmp_ctx);
76                         *error_string = "Cannot allocate mem_ctx";
77                         return ENOMEM;
78                 }
79
80                 principals[i]->smb_krb5_context =
81                         talloc_reference(principals[i], smb_krb5_context);
82                 principals[i]->string_form =
83                         talloc_asprintf(principals[i], "%*.*s@%s",
84                                         (int)spn_el->values[i].length,
85                                         (int)spn_el->values[i].length,
86                                         (const char *)spn_el->values[i].data,
87                                         upper_realm);
88                 if (!principals[i]->string_form) {
89                         talloc_free(tmp_ctx);
90                         *error_string = "Cannot allocate full samAccountName";
91                         return ENOMEM;
92                 }
93
94                 ret = krb5_parse_name(smb_krb5_context->krb5_context,
95                                       principals[i]->string_form,
96                                       &principals[i]->principal);
97
98                 if (ret) {
99                         talloc_free(tmp_ctx);
100                         (*error_string) = smb_get_krb5_error_message(
101                                                 smb_krb5_context->krb5_context,
102                                                 ret, parent_ctx);
103                         return ret;
104                 }
105
106                 /* This song-and-dance effectivly puts the principal
107                  * into talloc, so we can't loose it. */
108                 talloc_set_destructor(principals[i], free_principal);
109         }
110
111         if (samAccountName) {
112                 principals[i] = talloc(principals, struct principal_container);
113                 if (!principals[i]) {
114                         talloc_free(tmp_ctx);
115                         *error_string = "Cannot allocate mem_ctx";
116                         return ENOMEM;
117                 }
118
119                 principals[i]->smb_krb5_context =
120                         talloc_reference(principals[i], smb_krb5_context);
121                 principals[i]->string_form =
122                         talloc_asprintf(parent_ctx, "%s@%s",
123                                         samAccountName, upper_realm);
124                 if (!principals[i]->string_form) {
125                         talloc_free(tmp_ctx);
126                         *error_string = "Cannot allocate full samAccountName";
127                         return ENOMEM;
128                 }
129
130                 ret = krb5_make_principal(smb_krb5_context->krb5_context,
131                                           &principals[i]->principal,
132                                           upper_realm, samAccountName,
133                                           NULL);
134                 if (ret) {
135                         talloc_free(tmp_ctx);
136                         (*error_string) = smb_get_krb5_error_message(
137                                                 smb_krb5_context->krb5_context,
138                                                 ret, parent_ctx);
139                         return ret;
140                 }
141
142                 /* This song-and-dance effectively puts the principal
143                  * into talloc, so we can't loose it. */
144                 talloc_set_destructor(principals[i], free_principal);
145                 i++;
146         }
147
148         principals[i] = NULL;
149         *principals_out = talloc_steal(parent_ctx, principals);
150
151         talloc_free(tmp_ctx);
152         return ret;
153 }
154
155 static krb5_error_code salt_principal_from_msg(TALLOC_CTX *parent_ctx,
156                                 struct ldb_message *msg,
157                                 struct smb_krb5_context *smb_krb5_context,
158                                 krb5_principal *salt_princ,
159                                 const char **error_string)
160 {
161         const char *salt_principal = ldb_msg_find_attr_as_string(msg,
162                                                 "saltPrincipal", NULL);
163         const char *samAccountName = ldb_msg_find_attr_as_string(msg,
164                                                 "samAccountName", NULL);
165         const char *realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
166
167         struct principal_container *mem_ctx;
168         krb5_error_code ret;
169         char *machine_username;
170         char *salt_body;
171         char *lower_realm;
172         char *upper_realm;
173
174         TALLOC_CTX *tmp_ctx;
175
176         if (salt_principal) {
177                 return parse_principal(parent_ctx, salt_principal,
178                                         smb_krb5_context, salt_princ,
179                                         error_string);
180         }
181
182         if (!samAccountName) {
183                 (*error_string) = "Cannot determine salt principal, no "
184                                 "saltPrincipal or samAccountName specified";
185                 return EINVAL;
186         }
187
188
189         mem_ctx = talloc(parent_ctx, struct principal_container);
190         if (!mem_ctx) {
191                 *error_string = "Cannot allocate mem_ctx";
192                 return ENOMEM;
193         }
194
195         tmp_ctx = talloc_new(mem_ctx);
196         if (!tmp_ctx) {
197                 talloc_free(mem_ctx);
198                 *error_string = "Cannot allocate tmp_ctx";
199                 return ENOMEM;
200         }
201
202         if (!realm) {
203                 *error_string = "Cannot have a kerberos secret in "
204                                 "secrets.ldb without a realm";
205                 return EINVAL;
206         }
207
208         machine_username = talloc_strdup(tmp_ctx, samAccountName);
209         if (!machine_username) {
210                 talloc_free(mem_ctx);
211                 *error_string = "Cannot duplicate samAccountName";
212                 return ENOMEM;
213         }
214
215         if (machine_username[strlen(machine_username)-1] == '$') {
216                 machine_username[strlen(machine_username)-1] = '\0';
217         }
218
219         lower_realm = strlower_talloc(tmp_ctx, realm);
220         if (!lower_realm) {
221                 talloc_free(mem_ctx);
222                 *error_string = "Cannot allocate to lower case realm";
223                 return ENOMEM;
224         }
225
226         upper_realm = strupper_talloc(tmp_ctx, realm);
227         if (!upper_realm) {
228                 talloc_free(mem_ctx);
229                 *error_string = "Cannot allocate to upper case realm";
230                 return ENOMEM;
231         }
232
233         salt_body = talloc_asprintf(tmp_ctx, "%s.%s", machine_username,
234                                     lower_realm);
235         talloc_free(lower_realm);
236         talloc_free(machine_username);
237         if (!salt_body) {
238                 talloc_free(mem_ctx);
239                 *error_string = "Cannot form salt principal body";
240                 return ENOMEM;
241         }
242
243         ret = krb5_make_principal(smb_krb5_context->krb5_context, salt_princ,
244                                   upper_realm,
245                                   "host", salt_body, NULL);
246         if (ret == 0) {
247                 /* This song-and-dance effectively puts the principal
248                  * into talloc, so we can't loose it. */
249                 mem_ctx->smb_krb5_context = talloc_reference(mem_ctx,
250                                                         smb_krb5_context);
251                 mem_ctx->principal = *salt_princ;
252                 talloc_set_destructor(mem_ctx, free_principal);
253         } else {
254                 (*error_string) = smb_get_krb5_error_message(
255                                         smb_krb5_context->krb5_context,
256                                         ret, parent_ctx);
257         }
258         talloc_free(tmp_ctx);
259         return ret;
260 }
261
262 /* Translate between the Microsoft msDS-SupportedEncryptionTypes values
263  * and the IETF encryption type values */
264 static krb5_enctype ms_suptype_to_ietf_enctype(uint32_t enctype_bitmap)
265 {
266         switch (enctype_bitmap) {
267         case ENC_CRC32:
268                 return ENCTYPE_DES_CBC_CRC;
269         case ENC_RSA_MD5:
270                 return ENCTYPE_DES_CBC_MD5;
271         case ENC_RC4_HMAC_MD5:
272                 return ENCTYPE_ARCFOUR_HMAC_MD5;
273         case ENC_HMAC_SHA1_96_AES128:
274                 return ENCTYPE_AES128_CTS_HMAC_SHA1_96;
275         case ENC_HMAC_SHA1_96_AES256:
276                 return ENCTYPE_AES256_CTS_HMAC_SHA1_96;
277         default:
278                 return 0;
279         }
280 }
281
282 /* Return an array of krb5_enctype values */
283 static krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx,
284                                                 uint32_t enctype_bitmap,
285                                                 krb5_enctype **enctypes)
286 {
287         unsigned int i, j = 0;
288         *enctypes = talloc_zero_array(mem_ctx, krb5_enctype,
289                                         (8 * sizeof(enctype_bitmap)) + 1);
290         if (!*enctypes) {
291                 return ENOMEM;
292         }
293         for (i = 0; i < (8 * sizeof(enctype_bitmap)); i++) {
294                 uint32_t bit_value = (1 << i) & enctype_bitmap;
295                 if (bit_value & enctype_bitmap) {
296                         (*enctypes)[j] = ms_suptype_to_ietf_enctype(bit_value);
297                         if (!(*enctypes)[j]) {
298                                 continue;
299                         }
300                         j++;
301                 }
302         }
303         (*enctypes)[j] = 0;
304         return 0;
305 }
306
307 static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
308                                        struct principal_container **principals,
309                                        krb5_principal salt_princ,
310                                        int kvno,
311                                        const char *password_s,
312                                        krb5_context krb5_context,
313                                        krb5_enctype *enctypes,
314                                        krb5_keytab keytab,
315                                        const char **error_string)
316 {
317         unsigned int i, p;
318         krb5_error_code ret;
319         krb5_data password;
320
321         password.data = discard_const_p(char *, password_s);
322         password.length = strlen(password_s);
323
324         for (i = 0; enctypes[i]; i++) {
325                 krb5_keytab_entry entry;
326
327                 ZERO_STRUCT(entry);
328
329                 ret = create_kerberos_key_from_string_direct(krb5_context,
330                                                 salt_princ, &password,
331                                                 &entry.keyblock, enctypes[i]);
332                 if (ret != 0) {
333                         return ret;
334                 }
335
336                 entry.vno = kvno;
337
338                 for (p = 0; principals[p]; p++) {
339                         entry.principal = principals[p]->principal;
340                         ret = krb5_kt_add_entry(krb5_context,
341                                                 keytab, &entry);
342                         if (ret != 0) {
343                                 char *k5_error_string =
344                                         smb_get_krb5_error_message(
345                                                 krb5_context, ret, NULL);
346                                 *error_string = talloc_asprintf(parent_ctx,
347                                         "Failed to add enctype %d entry for "
348                                         "%s(kvno %d) to keytab: %s\n",
349                                         (int)enctypes[i],
350                                         principals[p]->string_form,
351                                         kvno, k5_error_string);
352
353                                 talloc_free(k5_error_string);
354                                 krb5_free_keyblock_contents(krb5_context,
355                                                             &entry.keyblock);
356                                 return ret;
357                         }
358
359                         DEBUG(5, ("Added %s(kvno %d) to keytab (enctype %d)\n",
360                                   principals[p]->string_form, kvno,
361                                   (int)enctypes[i]));
362                 }
363                 krb5_free_keyblock_contents(krb5_context, &entry.keyblock);
364         }
365         return 0;
366 }
367
368 static krb5_error_code create_keytab(TALLOC_CTX *parent_ctx,
369                                      struct ldb_message *msg,
370                                      struct principal_container **principals,
371                                      struct smb_krb5_context *smb_krb5_context,
372                                      krb5_keytab keytab,
373                                      bool add_old,
374                                      const char **error_string)
375 {
376         krb5_error_code ret;
377         const char *password_s;
378         const char *old_secret;
379         int kvno;
380         uint32_t enctype_bitmap;
381         krb5_principal salt_princ;
382         krb5_enctype *enctypes;
383         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
384         if (!mem_ctx) {
385                 *error_string = "unable to allocate tmp_ctx for create_keytab";
386                 return ENOMEM;
387         }
388
389         /* The salt used to generate these entries may be different however,
390          * fetch that */
391         ret = salt_principal_from_msg(mem_ctx, msg,
392                                       smb_krb5_context,
393                                       &salt_princ, error_string);
394         if (ret) {
395                 talloc_free(mem_ctx);
396                 return ret;
397         }
398
399         kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
400
401         /* Finally, do the dance to get the password to put in the entry */
402         password_s =  ldb_msg_find_attr_as_string(msg, "secret", NULL);
403
404         if (!password_s) {
405                 /* There is no password here, so nothing to do */
406                 talloc_free(mem_ctx);
407                 return 0;
408         }
409
410         if (add_old && kvno != 0) {
411                 old_secret = ldb_msg_find_attr_as_string(msg,
412                                                         "priorSecret", NULL);
413         } else {
414                 old_secret = NULL;
415         }
416
417         enctype_bitmap = (uint32_t)ldb_msg_find_attr_as_int(msg,
418                                         "msDS-SupportedEncryptionTypes",
419                                         ENC_ALL_TYPES);
420
421         ret = ms_suptypes_to_ietf_enctypes(mem_ctx, enctype_bitmap, &enctypes);
422         if (ret) {
423                 *error_string = talloc_asprintf(parent_ctx,
424                                         "create_keytab: generating list of "
425                                         "encryption types failed (%s)\n",
426                                         smb_get_krb5_error_message(
427                                                 smb_krb5_context->krb5_context,
428                                                 ret, mem_ctx));
429                 talloc_free(mem_ctx);
430                 return ret;
431         }
432
433         ret = keytab_add_keys(mem_ctx, principals,
434                               salt_princ, kvno, password_s,
435                               smb_krb5_context->krb5_context,
436                               enctypes, keytab, error_string);
437         if (ret) {
438                 talloc_free(mem_ctx);
439                 return ret;
440         }
441
442         if (old_secret) {
443                 ret = keytab_add_keys(mem_ctx, principals,
444                                       salt_princ, kvno - 1, old_secret,
445                                       smb_krb5_context->krb5_context,
446                                       enctypes, keytab, error_string);
447                 if (ret) {
448                         talloc_free(mem_ctx);
449                         return ret;
450                 }
451         }
452
453         talloc_free(mem_ctx);
454         return ret;
455 }
456
457 /*
458  * Walk the keytab, looking for entries of this principal name,
459  * with KVNO other than current kvno -1.
460  *
461  * These entries are now stale,
462  * we only keep the current and previous entries around.
463  *
464  * Inspired by the code in Samba3 for 'use kerberos keytab'.
465  */
466
467 static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
468                                           struct ldb_message *msg,
469                                           struct principal_container **principals,
470                                           bool delete_all_kvno,
471                                           krb5_context krb5_context,
472                                           krb5_keytab keytab,
473                                           bool *found_previous,
474                                           const char **error_string)
475 {
476         krb5_error_code ret, ret2;
477         krb5_kt_cursor cursor;
478         int kvno;
479         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
480
481         if (!mem_ctx) {
482                 return ENOMEM;
483         }
484
485         *found_previous = false;
486
487         kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
488
489         /* for each entry in the keytab */
490         ret = krb5_kt_start_seq_get(krb5_context, keytab, &cursor);
491         switch (ret) {
492         case 0:
493                 break;
494         case HEIM_ERR_OPNOTSUPP:
495         case ENOENT:
496         case KRB5_KT_END:
497                 /* no point enumerating if there isn't anything here */
498                 talloc_free(mem_ctx);
499                 return 0;
500         default:
501                 *error_string = talloc_asprintf(parent_ctx,
502                         "failed to open keytab for read of old entries: %s\n",
503                         smb_get_krb5_error_message(krb5_context,
504                                                    ret, mem_ctx));
505                 talloc_free(mem_ctx);
506                 return ret;
507         }
508
509         while (!ret) {
510                 unsigned int i;
511                 bool matched = false;
512                 krb5_keytab_entry entry;
513                 ret = krb5_kt_next_entry(krb5_context, keytab,
514                                          &entry, &cursor);
515                 if (ret) {
516                         break;
517                 }
518                 for (i = 0; principals[i]; i++) {
519                         /* if it matches our principal */
520                         if (krb5_kt_compare(krb5_context, &entry,
521                                             principals[i]->principal, 0, 0)) {
522                                 matched = true;
523                                 break;
524                         }
525                 }
526
527                 if (!matched) {
528                         /* Free the entry,
529                          * it wasn't the one we were looking for anyway */
530                         krb5_kt_free_entry(krb5_context, &entry);
531                         continue;
532                 }
533
534                 /* delete it, if it is not kvno -1 */
535                 if (entry.vno != (kvno - 1 )) {
536                         /* Release the enumeration.  We are going to
537                          * have to start this from the top again,
538                          * because deletes during enumeration may not
539                          * always be consistent.
540                          *
541                          * Also, the enumeration locks a FILE: keytab
542                          */
543
544                         krb5_kt_end_seq_get(krb5_context, keytab, &cursor);
545
546                         ret = krb5_kt_remove_entry(krb5_context, keytab, &entry);
547                         krb5_kt_free_entry(krb5_context, &entry);
548
549                         /* Deleted: Restart from the top */
550                         ret2 = krb5_kt_start_seq_get(krb5_context,
551                                                      keytab, &cursor);
552                         if (ret2) {
553                                 krb5_kt_free_entry(krb5_context, &entry);
554                                 DEBUG(1, ("failed to restart enumeration of keytab: %s\n",
555                                           smb_get_krb5_error_message(krb5_context,
556                                                                     ret, mem_ctx)));
557
558                                 talloc_free(mem_ctx);
559                                 return ret2;
560                         }
561
562                         if (ret) {
563                                 break;
564                         }
565
566                 } else {
567                         *found_previous = true;
568                 }
569
570                 /* Free the entry, we don't need it any more */
571                 krb5_kt_free_entry(krb5_context, &entry);
572         }
573         krb5_kt_end_seq_get(krb5_context, keytab, &cursor);
574
575         switch (ret) {
576         case 0:
577                 break;
578         case ENOENT:
579         case KRB5_KT_END:
580                 ret = 0;
581                 break;
582         default:
583                 *error_string = talloc_asprintf(parent_ctx,
584                         "failed in deleting old entries for principal: %s\n",
585                         smb_get_krb5_error_message(krb5_context,
586                                                    ret, mem_ctx));
587         }
588         talloc_free(mem_ctx);
589         return ret;
590 }
591
592 krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
593                                        struct smb_krb5_context *smb_krb5_context,
594                                        struct ldb_context *ldb,
595                                        struct ldb_message *msg,
596                                        bool delete_all_kvno,
597                                        const char **error_string)
598 {
599         krb5_error_code ret;
600         bool found_previous;
601         TALLOC_CTX *mem_ctx = talloc_new(NULL);
602         struct keytab_container *keytab_container;
603         struct principal_container **principals;
604         const char *keytab_name;
605
606         if (!mem_ctx) {
607                 return ENOMEM;
608         }
609
610         keytab_name = keytab_name_from_msg(mem_ctx, ldb, msg);
611         if (!keytab_name) {
612                 return ENOENT;
613         }
614
615         ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context,
616                                         keytab_name, &keytab_container);
617
618         if (ret != 0) {
619                 talloc_free(mem_ctx);
620                 return ret;
621         }
622
623         DEBUG(5, ("Opened keytab %s\n", keytab_name));
624
625         /* Get the principal we will store the new keytab entries under */
626         ret = principals_from_msg(mem_ctx, msg, smb_krb5_context,
627                                         &principals, error_string);
628
629         if (ret != 0) {
630                 *error_string = talloc_asprintf(parent_ctx,
631                         "Failed to load principals from ldb message: %s\n",
632                         *error_string);
633                 talloc_free(mem_ctx);
634                 return ret;
635         }
636
637         ret = remove_old_entries(mem_ctx, msg, principals, delete_all_kvno,
638                                  smb_krb5_context->krb5_context,
639                                  keytab_container->keytab,
640                                  &found_previous, error_string);
641         if (ret != 0) {
642                 *error_string = talloc_asprintf(parent_ctx,
643                         "Failed to remove old principals from keytab: %s\n",
644                         *error_string);
645                 talloc_free(mem_ctx);
646                 return ret;
647         }
648
649         if (!delete_all_kvno) {
650                 /* Create a new keytab.  If during the cleanout we found
651                  * entires for kvno -1, then don't try and duplicate them.
652                  * Otherwise, add kvno, and kvno -1 */
653
654                 ret = create_keytab(mem_ctx, msg, principals,
655                                     smb_krb5_context,
656                                     keytab_container->keytab,
657                                     found_previous ? false : true,
658                                     error_string);
659         }
660         talloc_free(mem_ctx);
661         return ret;
662 }
663
664 krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
665                                 struct cli_credentials *machine_account,
666                                 struct smb_krb5_context *smb_krb5_context,
667                                 struct keytab_container **keytab_container)
668 {
669         krb5_error_code ret;
670         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
671         const char *rand_string;
672         const char *keytab_name;
673         struct ldb_message *msg;
674         const char *error_string;
675         if (!mem_ctx) {
676                 return ENOMEM;
677         }
678
679         *keytab_container = talloc(mem_ctx, struct keytab_container);
680
681         rand_string = generate_random_str(mem_ctx, 16);
682         if (!rand_string) {
683                 talloc_free(mem_ctx);
684                 return ENOMEM;
685         }
686
687         keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s",
688                                       rand_string);
689         if (!keytab_name) {
690                 talloc_free(mem_ctx);
691                 return ENOMEM;
692         }
693
694         ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context,
695                                             keytab_name, keytab_container);
696         if (ret) {
697                 return ret;
698         }
699
700         msg = ldb_msg_new(mem_ctx);
701         if (!msg) {
702                 talloc_free(mem_ctx);
703                 return ENOMEM;
704         }
705         ldb_msg_add_string(msg, "krb5Keytab", keytab_name);
706         ldb_msg_add_string(msg, "secret",
707                            cli_credentials_get_password(machine_account));
708         ldb_msg_add_string(msg, "samAccountName",
709                            cli_credentials_get_username(machine_account));
710         ldb_msg_add_string(msg, "realm",
711                            cli_credentials_get_realm(machine_account));
712         ldb_msg_add_fmt(msg, "msDS-KeyVersionNumber", "%d",
713                            (int)cli_credentials_get_kvno(machine_account));
714
715         ret = smb_krb5_update_keytab(mem_ctx, smb_krb5_context, NULL,
716                                      msg, false, &error_string);
717         if (ret == 0) {
718                 talloc_steal(parent_ctx, *keytab_container);
719         } else {
720                 DEBUG(0, ("Failed to create in-memory keytab: %s\n",
721                           error_string));
722                 *keytab_container = NULL;
723         }
724         talloc_free(mem_ctx);
725         return ret;
726 }