2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Simo Sorce 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "lib/ldb/include/ldb_private.h"
28 #include "auth/gensec/gensec.h"
29 #include "system/time.h"
37 return 1 if a specific attribute has been requested
39 static int do_attribute(const char * const *attrs, const char *name)
41 return attrs == NULL ||
42 ldb_attr_in_list(attrs, name) ||
43 ldb_attr_in_list(attrs, "*");
48 add dynamically generated attributes to rootDSE result
50 static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_request *req)
52 struct private_data *priv = talloc_get_type(module->private_data, struct private_data);
53 struct ldb_search *s = &req->op.search;
54 struct ldb_message *msg;
55 struct cli_credentials *server_creds;
57 /* this is gross, and will be removed when I change ldb_result not
58 to be so pointer crazy :-) */
59 if (s->res->msgs == NULL) {
63 msg = s->res->msgs[0];
65 msg->dn = ldb_dn_explode(msg, "");
67 if (do_attribute(s->attrs, "currentTime")) {
68 if (ldb_msg_add_steal_string(msg, "currentTime",
69 ldb_timestring(msg, time(NULL))) != 0) {
74 if (do_attribute(s->attrs, "supportedControl")) {
76 for (i = 0; i < priv->num_controls; i++) {
77 char *control = talloc_strdup(msg, priv->controls[i]);
81 if (ldb_msg_add_steal_string(msg, "supportedControl",
88 server_creds = talloc_get_type(ldb_get_opaque(module->ldb, "server_credentials"),
89 struct cli_credentials);
90 if (server_creds && do_attribute(s->attrs, "supportedSASLMechanisms")) {
91 struct gensec_security_ops **backends = gensec_security_all();
92 enum credentials_use_kerberos use_kerberos
93 = cli_credentials_get_kerberos_state(server_creds);
94 struct gensec_security_ops **ops
95 = gensec_use_kerberos_mechs(req, backends, use_kerberos);
97 for (i = 0; ops && ops[i]; i++) {
98 if (ops[i]->sasl_name) {
99 char *sasl_name = talloc_strdup(msg, ops[i]->sasl_name);
103 if (ldb_msg_add_steal_string(msg, "supportedSASLMechanisms",
111 if (do_attribute(s->attrs, "highestCommittedUSN")) {
112 if (module->ldb->sequence_number != NULL &&
113 ldb_msg_add_fmt(msg, "highestCommittedUSN",
114 "%llu", module->ldb->sequence_number(module->ldb)) != 0) {
119 /* TODO: lots more dynamic attributes should be added here */
124 return LDB_ERR_OPERATIONS_ERROR;
128 handle search requests
130 static int rootdse_search_bytree(struct ldb_module *module, struct ldb_request *req)
132 struct ldb_search *s = &req->op.search;
136 /* see if its for the rootDSE */
137 if (s->scope != LDB_SCOPE_BASE ||
138 (s->base && s->base->comp_num != 0)) {
139 return ldb_next_request(module, req);
142 tmp_ctx = talloc_new(module);
144 /* in our db we store the rootDSE with a DN of cn=rootDSE */
145 s->base = ldb_dn_explode(tmp_ctx, "cn=rootDSE");
146 s->tree = ldb_parse_tree(tmp_ctx, "dn=*");
147 if (s->base == NULL || s->tree == NULL) {
148 ldb_oom(module->ldb);
149 talloc_free(tmp_ctx);
150 return LDB_ERR_OPERATIONS_ERROR;
153 /* grab the static contents of the record */
154 ret = ldb_next_request(module, req);
156 req->op.search.res = s->res;
158 if (ret == LDB_SUCCESS) {
159 ret = rootdse_add_dynamic(module, req);
162 talloc_free(tmp_ctx);
167 static int rootdse_register_control(struct ldb_module *module, struct ldb_request *req)
169 struct private_data *priv = talloc_get_type(module->private_data, struct private_data);
172 list = talloc_realloc(priv, priv->controls, char *, priv->num_controls + 1);
174 return LDB_ERR_OPERATIONS_ERROR;
177 list[priv->num_controls] = talloc_strdup(list, req->op.reg.oid);
178 if (!list[priv->num_controls]) {
179 return LDB_ERR_OPERATIONS_ERROR;
182 priv->num_controls += 1;
183 priv->controls = list;
189 static int rootdse_request(struct ldb_module *module, struct ldb_request *req)
191 switch (req->operation) {
193 return rootdse_search_bytree(module, req);
194 case LDB_REQ_REGISTER:
195 return rootdse_register_control(module, req);
199 return ldb_next_request(module, req);
202 static const struct ldb_module_ops rootdse_ops = {
204 .request = rootdse_request
207 struct ldb_module *rootdse_module_init(struct ldb_context *ldb, const char *options[])
209 struct ldb_module *ctx;
210 struct private_data *data;
212 ctx = talloc(ldb, struct ldb_module);
216 data = talloc(ctx, struct private_data);
222 data->num_controls = 0;
223 data->controls = NULL;
224 ctx->private_data = data;
227 ctx->prev = ctx->next = NULL;
228 ctx->ops = &rootdse_ops;