r11952: added a rootdse module. This will replace the existing rootdse code in
[kai/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / rootdse.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    rootDSE ldb module
5
6    Copyright (C) Andrew Tridgell 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 2 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    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "lib/ldb/include/ldb.h"
25 #include "lib/ldb/include/ldb_errors.h"
26 #include "lib/ldb/include/ldb_private.h"
27 #include <time.h>
28
29 /*
30   return 1 if a specific attribute has been requested
31 */
32 static int do_attribute(const char * const *attrs, const char *name)
33 {
34         return attrs == NULL ||
35                 ldb_attr_in_list(attrs, name) ||
36                 ldb_attr_in_list(attrs, "*");
37 }
38
39 /*
40   add dynamically generated attributes to rootDSE result
41 */
42 static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_request *req)
43 {
44         struct ldb_search *s = &req->op.search;
45         struct ldb_message *msg;
46
47         /* this is gross, and will be removed when I change ldb_result not
48            to be so pointer crazy :-) */
49         if (s->res[0][0].msgs == NULL) {
50                 return LDB_SUCCESS;
51         }
52
53         msg = s->res[0][0].msgs[0];
54
55         msg->dn = ldb_dn_explode(msg, "");
56
57         if (do_attribute(s->attrs, "currentTime")) {
58                 if (ldb_msg_add_string(msg, "currentTime", 
59                                        ldb_timestring(msg, time(NULL))) != 0) {
60                         goto failed;
61                 }
62         }
63
64         /* TODO: lots more dynamic attributes should be added here */
65
66         return 0;
67
68 failed:
69         return LDB_ERR_OPERATIONS_ERROR;
70 }
71
72 /*
73   handle search requests
74 */
75 static int rootdse_search_bytree(struct ldb_module *module, struct ldb_request *req)
76 {
77 //      struct ldb_request r = *req;
78         struct ldb_search *s = &req->op.search;
79         int ret;
80         TALLOC_CTX *tmp_ctx;
81
82         /* see if its for the rootDSE */
83         if (s->scope != LDB_SCOPE_BASE ||
84             (s->base && s->base->comp_num != 0)) {
85                 return ldb_next_request(module, req);
86         }
87
88         tmp_ctx = talloc_new(module);
89
90         /* in our db we store the rootDSE with a DN of cn=rootDSE */
91         s->base = ldb_dn_explode(tmp_ctx, "cn=rootDSE");
92         s->tree = ldb_parse_tree(tmp_ctx, "dn=*");
93         if (s->base == NULL || s->tree == NULL) {
94                 ldb_oom(module->ldb);
95                 talloc_free(tmp_ctx);
96                 return LDB_ERR_OPERATIONS_ERROR;
97         }
98
99         /* grab the static contents of the record */
100         ret = ldb_next_request(module, req);
101
102         req->op.search.res = s->res;
103
104         if (ret == LDB_SUCCESS) {
105                 ret = rootdse_add_dynamic(module, req);
106         }
107
108         talloc_free(tmp_ctx);
109
110         return ret;
111 }
112
113
114 static int rootdse_request(struct ldb_module *module, struct ldb_request *req)
115 {
116         switch (req->operation) {
117         case LDB_REQ_SEARCH:
118                 return rootdse_search_bytree(module, req);
119         default:
120                 break;
121         }
122         return ldb_next_request(module, req);
123 }
124
125 static const struct ldb_module_ops rootdse_ops = {
126         .name           = "rootdse",
127         .request        = rootdse_request
128 };
129
130 #ifdef HAVE_DLOPEN_DISABLED
131 struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
132 #else
133 struct ldb_module *rootdse_module_init(struct ldb_context *ldb, const char *options[])
134 #endif
135 {
136         struct ldb_module *ctx;
137
138         ctx = talloc(ldb, struct ldb_module);
139         if (!ctx)
140                 return NULL;
141
142         ctx->ldb = ldb;
143         ctx->prev = ctx->next = NULL;
144         ctx->ops = &rootdse_ops;
145         ctx->private_data = NULL;
146
147         return ctx;
148 }
149