pytest:sid_strings: Do bad SIDs fail differently in simple-bind?
[Samba.git] / source4 / libnet / libnet_export_keytab.c
blob8f548e14eeb76f2404eb7f2ae9ee0028c6e8335a
1 /*
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/>.
21 #include "includes.h"
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"
28 #include "kdc/sdb.h"
30 static NTSTATUS sdb_kt_copy(TALLOC_CTX *mem_ctx,
31 krb5_context context,
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 sentry = {};
38 krb5_keytab keytab;
39 krb5_error_code code = 0;
40 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
41 char *entry_principal = NULL;
42 bool copy_one_principal = (principal != NULL);
43 krb5_data password;
45 code = smb_krb5_kt_open_relative(context,
46 keytab_name,
47 true, /* write_access */
48 &keytab);
49 if (code != 0) {
50 *error_string = talloc_asprintf(mem_ctx,
51 "Failed to open keytab: %s",
52 keytab_name);
53 status = NT_STATUS_NO_SUCH_FILE;
54 goto done;
57 if (copy_one_principal) {
58 krb5_principal k5_princ;
60 code = smb_krb5_parse_name(context, principal, &k5_princ);
61 if (code != 0) {
62 *error_string = smb_get_krb5_error_message(context,
63 code,
64 mem_ctx);
65 status = NT_STATUS_UNSUCCESSFUL;
66 goto done;
69 code = samba_kdc_fetch(context, db_ctx, k5_princ,
70 SDB_F_GET_ANY | SDB_F_ADMIN_DATA,
71 0, &sentry);
73 krb5_free_principal(context, k5_princ);
74 } else {
75 code = samba_kdc_firstkey(context, db_ctx, &sentry);
78 for (; code == 0; code = samba_kdc_nextkey(context, db_ctx, &sentry)) {
79 int i;
81 code = krb5_unparse_name(context,
82 sentry.principal,
83 &entry_principal);
84 if (code != 0) {
85 *error_string = smb_get_krb5_error_message(context,
86 code,
87 mem_ctx);
88 status = NT_STATUS_UNSUCCESSFUL;
89 goto done;
92 if (sentry.keys.len == 0) {
93 SAFE_FREE(entry_principal);
94 sdb_entry_free(&sentry);
96 continue;
99 for (i = 0; i < sentry.keys.len; i++) {
100 struct sdb_key *s = &(sentry.keys.val[i]);
101 krb5_enctype enctype;
103 enctype = KRB5_KEY_TYPE(&(s->key));
104 password.length = KRB5_KEY_LENGTH(&s->key);
105 password.data = (char *)KRB5_KEY_DATA(&s->key);
107 DBG_INFO("smb_krb5_kt_add_entry for enctype=0x%04x\n",
108 (int)enctype);
109 code = smb_krb5_kt_add_entry(context,
110 keytab,
111 sentry.kvno,
112 entry_principal,
113 NULL,
114 enctype,
115 &password,
116 true); /* no_salt */
117 if (code != 0) {
118 status = NT_STATUS_UNSUCCESSFUL;
119 *error_string = smb_get_krb5_error_message(context,
120 code,
121 mem_ctx);
122 DEBUG(0, ("smb_krb5_kt_add_entry failed code=%d, error = %s\n",
123 code, *error_string));
124 goto done;
128 if (copy_one_principal) {
129 break;
132 SAFE_FREE(entry_principal);
133 sdb_entry_free(&sentry);
136 if (code != 0 && code != SDB_ERR_NOENTRY) {
137 *error_string = smb_get_krb5_error_message(context,
138 code,
139 mem_ctx);
140 status = NT_STATUS_NO_SUCH_USER;
141 goto done;
144 status = NT_STATUS_OK;
145 done:
146 SAFE_FREE(entry_principal);
147 sdb_entry_free(&sentry);
149 return status;
152 NTSTATUS libnet_export_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_export_keytab *r)
154 krb5_error_code ret;
155 struct smb_krb5_context *smb_krb5_context;
156 struct samba_kdc_base_context *base_ctx;
157 struct samba_kdc_db_context *db_ctx = NULL;
158 const char *error_string = NULL;
159 NTSTATUS status;
161 ret = smb_krb5_init_context(ctx, ctx->lp_ctx, &smb_krb5_context);
162 if (ret) {
163 return NT_STATUS_NO_MEMORY;
166 base_ctx = talloc_zero(mem_ctx, struct samba_kdc_base_context);
167 if (base_ctx == NULL) {
168 return NT_STATUS_NO_MEMORY;
171 base_ctx->ev_ctx = ctx->event_ctx;
172 base_ctx->lp_ctx = ctx->lp_ctx;
174 status = samba_kdc_setup_db_ctx(mem_ctx, base_ctx, &db_ctx);
175 if (!NT_STATUS_IS_OK(status)) {
176 return status;
179 if (r->in.principal != NULL) {
180 DEBUG(0, ("Export one principal to %s\n", r->in.keytab_name));
181 status = sdb_kt_copy(mem_ctx,
182 smb_krb5_context->krb5_context,
183 db_ctx,
184 r->in.keytab_name,
185 r->in.principal,
186 &error_string);
187 } else {
188 unlink(r->in.keytab_name);
189 DEBUG(0, ("Export complete keytab to %s\n", r->in.keytab_name));
190 status = sdb_kt_copy(mem_ctx,
191 smb_krb5_context->krb5_context,
192 db_ctx,
193 r->in.keytab_name,
194 NULL,
195 &error_string);
198 talloc_free(db_ctx);
199 talloc_free(base_ctx);
201 if (!NT_STATUS_IS_OK(status)) {
202 r->out.error_string = error_string;
205 return status;