2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
5 Copyright (C) Andreas Schneider <asn@samba.org> 2016
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/kerberos.h"
23 #include "auth/kerberos/kerberos.h"
24 #include "kdc/samba_kdc.h"
25 #include "libnet/libnet_export_keytab.h"
27 #include "kdc/db-glue.h"
30 static NTSTATUS
sdb_kt_copy(TALLOC_CTX
*mem_ctx
,
32 struct samba_kdc_db_context
*db_ctx
,
33 const char *keytab_name
,
34 const char *principal
,
35 const char **error_string
)
37 struct sdb_entry_ex sentry
= {
41 krb5_error_code code
= 0;
42 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
43 char *entry_principal
= NULL
;
44 bool copy_one_principal
= (principal
!= NULL
);
47 code
= smb_krb5_kt_open_relative(context
,
49 true, /* write_access */
52 *error_string
= talloc_asprintf(mem_ctx
,
53 "Failed to open keytab: %s",
55 status
= NT_STATUS_NO_SUCH_FILE
;
59 if (copy_one_principal
) {
60 krb5_principal k5_princ
;
62 code
= smb_krb5_parse_name(context
, principal
, &k5_princ
);
64 *error_string
= smb_get_krb5_error_message(context
,
67 status
= NT_STATUS_UNSUCCESSFUL
;
71 code
= samba_kdc_fetch(context
, db_ctx
, k5_princ
,
72 SDB_F_GET_ANY
, 0, &sentry
);
74 krb5_free_principal(context
, k5_princ
);
76 code
= samba_kdc_firstkey(context
, db_ctx
, &sentry
);
79 for (; code
== 0; code
= samba_kdc_nextkey(context
, db_ctx
, &sentry
)) {
82 code
= krb5_unparse_name(context
,
83 sentry
.entry
.principal
,
86 *error_string
= smb_get_krb5_error_message(context
,
89 status
= NT_STATUS_UNSUCCESSFUL
;
93 if (sentry
.entry
.keys
.len
== 0) {
94 SAFE_FREE(entry_principal
);
95 sdb_free_entry(&sentry
);
96 sentry
= (struct sdb_entry_ex
) {
103 for (i
= 0; i
< sentry
.entry
.keys
.len
; i
++) {
104 struct sdb_key
*s
= &(sentry
.entry
.keys
.val
[i
]);
105 krb5_enctype enctype
;
107 enctype
= KRB5_KEY_TYPE(&(s
->key
));
108 password
.length
= KRB5_KEY_LENGTH(&s
->key
);
109 password
.data
= (char *)KRB5_KEY_DATA(&s
->key
);
111 DBG_INFO("smb_krb5_kt_add_entry for enctype=0x%04x\n",
113 code
= smb_krb5_kt_add_entry(context
,
121 false); /* keeyp_old_entries */
123 status
= NT_STATUS_UNSUCCESSFUL
;
124 *error_string
= smb_get_krb5_error_message(context
,
127 DEBUG(0, ("smb_krb5_kt_add_entry failed code=%d, error = %s\n",
128 code
, *error_string
));
133 if (copy_one_principal
) {
137 SAFE_FREE(entry_principal
);
138 sdb_free_entry(&sentry
);
139 sentry
= (struct sdb_entry_ex
) {
144 if (code
!= 0 && code
!= SDB_ERR_NOENTRY
) {
145 *error_string
= smb_get_krb5_error_message(context
,
148 status
= NT_STATUS_NO_SUCH_USER
;
152 status
= NT_STATUS_OK
;
154 SAFE_FREE(entry_principal
);
155 sdb_free_entry(&sentry
);
160 NTSTATUS
libnet_export_keytab(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
, struct libnet_export_keytab
*r
)
163 struct smb_krb5_context
*smb_krb5_context
;
164 struct samba_kdc_base_context
*base_ctx
;
165 struct samba_kdc_db_context
*db_ctx
= NULL
;
166 const char *error_string
= NULL
;
169 ret
= smb_krb5_init_context(ctx
, ctx
->lp_ctx
, &smb_krb5_context
);
171 return NT_STATUS_NO_MEMORY
;
174 base_ctx
= talloc_zero(mem_ctx
, struct samba_kdc_base_context
);
175 if (base_ctx
== NULL
) {
176 return NT_STATUS_NO_MEMORY
;
179 base_ctx
->ev_ctx
= ctx
->event_ctx
;
180 base_ctx
->lp_ctx
= ctx
->lp_ctx
;
182 status
= samba_kdc_setup_db_ctx(mem_ctx
, base_ctx
, &db_ctx
);
183 if (!NT_STATUS_IS_OK(status
)) {
187 if (r
->in
.principal
!= NULL
) {
188 DEBUG(0, ("Export one principal to %s\n", r
->in
.keytab_name
));
189 status
= sdb_kt_copy(mem_ctx
,
190 smb_krb5_context
->krb5_context
,
196 unlink(r
->in
.keytab_name
);
197 DEBUG(0, ("Export complete keytab to %s\n", r
->in
.keytab_name
));
198 status
= sdb_kt_copy(mem_ctx
,
199 smb_krb5_context
->krb5_context
,
207 talloc_free(base_ctx
);
209 if (!NT_STATUS_IS_OK(status
)) {
210 r
->out
.error_string
= error_string
;