r11555: - change socket_wrapper to support multiple IP's
[abartlet/samba.git/.git] / source4 / lib / ldb / modules / rdn_name.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb objectguid module
29  *
30  *  Description: add a unique objectGUID onto every new record
31  *
32  *  Author: Simo Sorce
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include <time.h>
39
40 static int rdn_name_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
41                                   enum ldb_scope scope, struct ldb_parse_tree *tree,
42                                   const char * const *attrs, struct ldb_message ***res)
43 {
44         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_search\n");
45         return ldb_next_search_bytree(module, base, scope, tree, attrs, res);
46 }
47
48 static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
49 {
50         int i;
51
52         for (i = 0; i < msg->num_elements; i++) {
53                 if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
54                         return &msg->elements[i];
55                 }
56         }
57
58         return NULL;
59 }
60
61 /* add_record: add crateTimestamp/modifyTimestamp attributes */
62 static int rdn_name_add_record(struct ldb_module *module, const struct ldb_message *msg)
63 {
64         struct ldb_message *msg2;
65         struct ldb_message_element *attribute;
66         struct ldb_dn_component *rdn;
67         int i, ret;
68
69         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
70
71         /* do not manipulate our control entries */
72         if (ldb_dn_is_special(msg->dn)) {
73                 return ldb_next_add_record(module, msg);
74         }
75
76         /* Perhaps someone above us knows better */
77         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
78                 return ldb_next_add_record(module, msg);
79         }
80
81         msg2 = talloc(module, struct ldb_message);
82         if (!msg2) {
83                 return -1;
84         }
85
86         msg2->dn = msg->dn;
87         msg2->num_elements = msg->num_elements;
88         msg2->private_data = msg->private_data;
89         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
90         for (i = 0; i < msg2->num_elements; i++) {
91                 msg2->elements[i] = msg->elements[i];
92         }
93
94         rdn = ldb_dn_get_rdn(msg2, msg2->dn);
95         if (!rdn) {
96                 talloc_free(msg2);
97                 return -1;
98         }
99         
100         if (ldb_msg_add_value(msg2, "name", &rdn->value) != 0) {
101                 talloc_free(msg2);
102                 return -1;
103         }
104
105         attribute = rdn_name_find_attribute(msg2, rdn->name);
106
107         if (!attribute) {
108                 if (ldb_msg_add_value(msg2, rdn->name, &rdn->value) != 0) {
109                         talloc_free(msg2);
110                         return -1;
111                 }
112         } else {
113                 const struct ldb_attrib_handler *handler
114                         = ldb_attrib_handler(module->ldb, rdn->name);
115                 for (i=0; i < attribute->num_values; i++) {
116                         if (handler->comparison_fn(module->ldb, msg2, &rdn->value, &attribute->values[i]) == 0) {
117                                 /* overwrite so it matches in case */
118                                 attribute->values[i] = rdn->value;
119                                 break;
120                         }
121                 }
122                 if (i == attribute->num_values) {
123                         ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, 
124                                       "RDN mismatch on %s: %s", 
125                                       ldb_dn_linearize(msg2, msg2->dn), rdn->name);
126                         talloc_free(msg2);
127                         return -1;
128                 }
129         }
130
131         ret = ldb_next_add_record(module, msg2);
132         talloc_free(msg2);
133
134         return ret;
135 }
136
137 /* modify_record: change modifyTimestamp as well */
138 static int rdn_name_modify_record(struct ldb_module *module, const struct ldb_message *msg)
139 {
140         struct ldb_message *msg2;
141         struct ldb_message_element *attribute;
142         struct ldb_dn_component *rdn;
143         int ret, i;
144
145         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_modify_record\n");
146
147         /* do not manipulate our control entries */
148         if (ldb_dn_is_special(msg->dn)) {
149                 return ldb_next_modify_record(module, msg);
150         }
151
152         /* Perhaps someone above us knows better */
153         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
154                 return ldb_next_modify_record(module, msg);
155         }
156
157         msg2 = talloc(module, struct ldb_message);
158         if (!msg2) {
159                 return -1;
160         }
161
162         msg2->dn = msg->dn;
163         msg2->num_elements = msg->num_elements;
164         msg2->private_data = msg->private_data;
165         msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
166         for (i = 0; i < msg2->num_elements; i++) {
167                 msg2->elements[i] = msg->elements[i];
168         }
169         
170         rdn = ldb_dn_get_rdn(msg2, msg2->dn);
171         if (!rdn) {
172                 talloc_free(msg2);
173                 return -1;
174         }
175         
176         if (ldb_msg_add_value(msg2, "name", &rdn->value) != 0) {
177                 talloc_free(msg2);
178                 return -1;
179         }
180
181         attribute = rdn_name_find_attribute(msg2, "name");
182         if (!attribute) {
183                 talloc_free(msg2);
184                 return -1;
185         }
186
187         attribute->flags = LDB_FLAG_MOD_REPLACE;
188
189         ret = ldb_next_modify_record(module, msg2);
190         talloc_free(msg2);
191
192         return ret;
193 }
194
195 static int rdn_name_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
196 {
197         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_rename_record\n");
198         return ldb_next_rename_record(module, olddn, newdn);
199 }
200
201 static const struct ldb_module_ops rdn_name_ops = {
202         .name              = "rdn_name",
203         .search_bytree     = rdn_name_search_bytree,
204         .add_record        = rdn_name_add_record,
205         .modify_record     = rdn_name_modify_record,
206         .rename_record     = rdn_name_rename_record
207 };
208
209
210 /* the init function */
211 #ifdef HAVE_DLOPEN_DISABLED
212  struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
213 #else
214 struct ldb_module *rdn_name_module_init(struct ldb_context *ldb, const char *options[])
215 #endif
216 {
217         struct ldb_module *ctx;
218
219         ctx = talloc(ldb, struct ldb_module);
220         if (!ctx)
221                 return NULL;
222
223         ctx->private_data = NULL;
224         ctx->ldb = ldb;
225         ctx->prev = ctx->next = NULL;
226         ctx->ops = &rdn_name_ops;
227
228         return ctx;
229 }