r11958: - fixed memory leaks in the ldb_result handling in ldb operations
[abartlet/samba.git/.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->msgs == NULL) {
50                 return LDB_SUCCESS;
51         }
52
53         msg = s->res->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_search *s = &req->op.search;
78         int ret;
79         TALLOC_CTX *tmp_ctx;
80
81         /* see if its for the rootDSE */
82         if (s->scope != LDB_SCOPE_BASE ||
83             (s->base && s->base->comp_num != 0)) {
84                 return ldb_next_request(module, req);
85         }
86
87         tmp_ctx = talloc_new(module);
88
89         /* in our db we store the rootDSE with a DN of cn=rootDSE */
90         s->base = ldb_dn_explode(tmp_ctx, "cn=rootDSE");
91         s->tree = ldb_parse_tree(tmp_ctx, "dn=*");
92         if (s->base == NULL || s->tree == NULL) {
93                 ldb_oom(module->ldb);
94                 talloc_free(tmp_ctx);
95                 return LDB_ERR_OPERATIONS_ERROR;
96         }
97
98         /* grab the static contents of the record */
99         ret = ldb_next_request(module, req);
100
101         req->op.search.res = s->res;
102
103         if (ret == LDB_SUCCESS) {
104                 ret = rootdse_add_dynamic(module, req);
105         }
106
107         talloc_free(tmp_ctx);
108
109         return ret;
110 }
111
112
113 static int rootdse_request(struct ldb_module *module, struct ldb_request *req)
114 {
115         switch (req->operation) {
116         case LDB_REQ_SEARCH:
117                 return rootdse_search_bytree(module, req);
118         default:
119                 break;
120         }
121         return ldb_next_request(module, req);
122 }
123
124 static const struct ldb_module_ops rootdse_ops = {
125         .name           = "rootdse",
126         .request        = rootdse_request
127 };
128
129 #ifdef HAVE_DLOPEN_DISABLED
130 struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
131 #else
132 struct ldb_module *rootdse_module_init(struct ldb_context *ldb, const char *options[])
133 #endif
134 {
135         struct ldb_module *ctx;
136
137         ctx = talloc(ldb, struct ldb_module);
138         if (!ctx)
139                 return NULL;
140
141         ctx->ldb = ldb;
142         ctx->prev = ctx->next = NULL;
143         ctx->ops = &rootdse_ops;
144         ctx->private_data = NULL;
145
146         return ctx;
147 }
148