4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 * Component: ldb update_keytabs module
25 * Description: Update keytabs whenever their matching secret record changes
27 * Author: Andrew Bartlett
31 #include "ldb/include/ldb_includes.h"
32 #include "auth/credentials/credentials.h"
33 #include "auth/credentials/credentials_krb5.h"
34 #include "system/kerberos.h"
35 #include "param/param.h"
38 struct cli_credentials
*creds
;
39 struct dn_list
*prev
, *next
;
42 struct update_kt_private
{
43 struct dn_list
*changed_dns
;
46 static int add_modified(struct ldb_module
*module
, struct ldb_dn
*dn
, bool delete) {
47 struct update_kt_private
*data
= talloc_get_type(module
->private_data
, struct update_kt_private
);
50 struct ldb_result
*res
;
51 const char *attrs
[] = { NULL
};
55 filter
= talloc_asprintf(data
, "(&(dn=%s)(&(objectClass=kerberosSecret)(privateKeytab=*)))",
56 ldb_dn_get_linearized(dn
));
59 return LDB_ERR_OPERATIONS_ERROR
;
62 ret
= ldb_search(module
->ldb
, data
, &res
,
63 dn
, LDB_SCOPE_BASE
, attrs
, "%s", filter
);
64 if (ret
!= LDB_SUCCESS
) {
69 if (res
->count
!= 1) {
70 /* if it's not a kerberosSecret then we don't have anything to update */
77 item
= talloc(data
->changed_dns
? (void *)data
->changed_dns
: (void *)data
, struct dn_list
);
81 return LDB_ERR_OPERATIONS_ERROR
;
84 item
->creds
= cli_credentials_init(item
);
86 DEBUG(1, ("cli_credentials_init failed!"));
89 return LDB_ERR_OPERATIONS_ERROR
;
92 cli_credentials_set_conf(item
->creds
, ldb_get_opaque(module
->ldb
, "loadparm"));
93 status
= cli_credentials_set_secrets(item
->creds
, ldb_get_opaque(module
->ldb
, "EventContext"), ldb_get_opaque(module
->ldb
, "loadparm"), module
->ldb
, NULL
, filter
);
95 if (NT_STATUS_IS_OK(status
)) {
97 /* Ensure we don't helpfully keep an old keytab entry */
98 cli_credentials_set_kvno(item
->creds
, cli_credentials_get_kvno(item
->creds
)+2);
100 cli_credentials_set_nt_hash(item
->creds
, NULL
,
103 DLIST_ADD_END(data
->changed_dns
, item
, struct dn_list
*);
109 static int update_kt_add(struct ldb_module
*module
, struct ldb_request
*req
)
112 ret
= ldb_next_request(module
, req
);
113 if (ret
!= LDB_SUCCESS
) {
116 return add_modified(module
, req
->op
.add
.message
->dn
, false);
120 static int update_kt_modify(struct ldb_module
*module
, struct ldb_request
*req
)
123 ret
= ldb_next_request(module
, req
);
124 if (ret
!= LDB_SUCCESS
) {
127 return add_modified(module
, req
->op
.mod
.message
->dn
, false);
131 static int update_kt_delete(struct ldb_module
*module
, struct ldb_request
*req
)
134 /* Before we delete it, record the details */
135 ret
= add_modified(module
, req
->op
.del
.dn
, true);
136 if (ret
!= LDB_SUCCESS
) {
139 return ldb_next_request(module
, req
);
143 static int update_kt_rename(struct ldb_module
*module
, struct ldb_request
*req
)
146 ret
= ldb_next_request(module
, req
);
147 if (ret
!= LDB_SUCCESS
) {
150 return add_modified(module
, req
->op
.rename
.newdn
, false);
153 /* end a transaction */
154 static int update_kt_end_trans(struct ldb_module
*module
)
156 struct update_kt_private
*data
= talloc_get_type(module
->private_data
, struct update_kt_private
);
159 for (p
=data
->changed_dns
; p
; p
= p
->next
) {
161 kret
= cli_credentials_update_keytab(p
->creds
, ldb_get_opaque(module
->ldb
, "EventContext"), ldb_get_opaque(module
->ldb
, "loadparm"));
163 talloc_free(data
->changed_dns
);
164 data
->changed_dns
= NULL
;
165 ldb_asprintf_errstring(module
->ldb
, "Failed to update keytab: %s", error_message(kret
));
166 return LDB_ERR_OPERATIONS_ERROR
;
170 talloc_free(data
->changed_dns
);
171 data
->changed_dns
= NULL
;
172 return ldb_next_end_trans(module
);
175 /* end a transaction */
176 static int update_kt_del_trans(struct ldb_module
*module
)
178 struct update_kt_private
*data
= talloc_get_type(module
->private_data
, struct update_kt_private
);
180 talloc_free(data
->changed_dns
);
181 data
->changed_dns
= NULL
;
183 return ldb_next_del_trans(module
);
186 static int update_kt_init(struct ldb_module
*module
)
188 struct update_kt_private
*data
;
190 data
= talloc(module
, struct update_kt_private
);
192 ldb_oom(module
->ldb
);
193 return LDB_ERR_OPERATIONS_ERROR
;
196 module
->private_data
= data
;
197 data
->changed_dns
= NULL
;
199 return ldb_next_init(module
);
202 _PUBLIC_
const struct ldb_module_ops ldb_update_keytab_module_ops
= {
203 .name
= "update_keytab",
204 .init_context
= update_kt_init
,
205 .add
= update_kt_add
,
206 .modify
= update_kt_modify
,
207 .rename
= update_kt_rename
,
208 .del
= update_kt_delete
,
209 .end_transaction
= update_kt_end_trans
,
210 .del_transaction
= update_kt_del_trans
,