r7593: simplified the memory management in the ldap code. Having a mem_ctx
[samba.git] / source4 / ldap_server / ldap_backend.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP server
4    Copyright (C) Stefan Metzmacher 2004
5    
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 2 of the License, or
9    (at your option) any later version.
10    
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.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "ldap_server/ldap_server.h"
23 #include "dlinklist.h"
24 #include "libcli/ldap/ldap.h"
25
26
27 struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type)
28 {
29         struct ldapsrv_reply *reply;
30
31         reply = talloc(call, struct ldapsrv_reply);
32         if (!reply) {
33                 return NULL;
34         }
35         reply->msg = talloc(reply, struct ldap_message);
36         if (reply->msg == NULL) {
37                 talloc_free(reply);
38                 return NULL;
39         }
40
41         reply->prev = reply->next = NULL;
42         reply->state = LDAPSRV_REPLY_STATE_NEW;
43         reply->msg->messageid = call->request->messageid;
44         reply->msg->type = type;
45
46         return reply;
47 }
48
49 NTSTATUS ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
50 {
51         DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
52         return NT_STATUS_OK;
53 }
54
55 struct ldapsrv_partition *ldapsrv_get_partition(struct ldapsrv_connection *conn, const char *dn, uint8_t scope)
56 {
57         if (scope == LDAP_SEARCH_SCOPE_BASE
58             && strcasecmp("", dn) == 0) {
59                 return conn->service->rootDSE;
60         }
61
62         return conn->service->default_partition;
63 }
64
65 NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
66 {
67         struct ldapsrv_reply *reply;
68         struct ldap_ExtendedResponse *r;
69
70         DEBUG(10,("Unwilling type[%d] id[%d]\n", call->request->type, call->request->messageid));
71
72         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
73         if (!reply) {
74                 return NT_STATUS_NO_MEMORY;
75         }
76
77         r = &reply->msg->r.ExtendedResponse;
78         r->response.resultcode = error;
79         r->response.dn = NULL;
80         r->response.errormessage = NULL;
81         r->response.referral = NULL;
82         r->name = NULL;
83         r->value.data = NULL;
84         r->value.length = 0;
85
86         return ldapsrv_queue_reply(call, reply);
87 }
88
89 static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
90 {
91         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
92         struct ldapsrv_partition *part;
93
94         DEBUG(10, ("SearchRequest"));
95         DEBUGADD(10, (" basedn: %s", req->basedn));
96         DEBUGADD(10, (" filter: %s\n", ldb_filter_from_tree(call, req->tree)));
97
98         part = ldapsrv_get_partition(call->conn, req->basedn, req->scope);
99
100         if (!part->ops->Search) {
101                 struct ldap_Result *done;
102                 struct ldapsrv_reply *done_r;
103
104                 done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
105                 if (!done_r) {
106                         return NT_STATUS_NO_MEMORY;
107                 }
108
109                 done = &done_r->msg->r.SearchResultDone;
110                 done->resultcode = 53;
111                 done->dn = NULL;
112                 done->errormessage = NULL;
113                 done->referral = NULL;
114
115                 return ldapsrv_queue_reply(call, done_r);
116         }
117
118         return part->ops->Search(part, call, req);
119 }
120
121 static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
122 {
123         struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
124         struct ldapsrv_partition *part;
125
126         DEBUG(10, ("ModifyRequest"));
127         DEBUGADD(10, (" dn: %s", req->dn));
128
129         part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
130
131         if (!part->ops->Modify) {
132                 return ldapsrv_unwilling(call, 53);
133         }
134
135         return part->ops->Modify(part, call, req);
136 }
137
138 static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
139 {
140         struct ldap_AddRequest *req = &call->request->r.AddRequest;
141         struct ldapsrv_partition *part;
142
143         DEBUG(10, ("AddRequest"));
144         DEBUGADD(10, (" dn: %s", req->dn));
145
146         part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
147
148         if (!part->ops->Add) {
149                 return ldapsrv_unwilling(call, 53);
150         }
151
152         return part->ops->Add(part, call, req);
153 }
154
155 static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
156 {
157         struct ldap_DelRequest *req = &call->request->r.DelRequest;
158         struct ldapsrv_partition *part;
159
160         DEBUG(10, ("DelRequest"));
161         DEBUGADD(10, (" dn: %s", req->dn));
162
163         part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
164
165         if (!part->ops->Del) {
166                 return ldapsrv_unwilling(call, 53);
167         }
168
169         return part->ops->Del(part, call, req);
170 }
171
172 static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
173 {
174         struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
175         struct ldapsrv_partition *part;
176
177         DEBUG(10, ("ModifyDNRequrest"));
178         DEBUGADD(10, (" dn: %s", req->dn));
179         DEBUGADD(10, (" newrdn: %s", req->newrdn));
180
181         part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
182
183         if (!part->ops->ModifyDN) {
184                 return ldapsrv_unwilling(call, 53);
185         }
186
187         return part->ops->ModifyDN(part, call, req);
188 }
189
190 static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
191 {
192         struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
193         struct ldapsrv_partition *part;
194
195         DEBUG(10, ("CompareRequest"));
196         DEBUGADD(10, (" dn: %s", req->dn));
197
198         part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
199
200         if (!part->ops->Compare) {
201                 return ldapsrv_unwilling(call, 53);
202         }
203
204         return part->ops->Compare(part, call, req);
205 }
206
207 static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
208 {
209 /*      struct ldap_AbandonRequest *req = &call->request.r.AbandonRequest;*/
210         DEBUG(10, ("AbandonRequest\n"));
211         return NT_STATUS_OK;
212 }
213
214 static NTSTATUS ldapsrv_ExtendedRequest(struct ldapsrv_call *call)
215 {
216 /*      struct ldap_ExtendedRequest *req = &call->request.r.ExtendedRequest;*/
217         struct ldapsrv_reply *reply;
218
219         DEBUG(10, ("Extended\n"));
220
221         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
222         if (!reply) {
223                 return NT_STATUS_NO_MEMORY;
224         }
225
226         ZERO_STRUCT(reply->msg->r);
227
228         return ldapsrv_queue_reply(call, reply);
229 }
230
231 NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
232 {
233         switch(call->request->type) {
234         case LDAP_TAG_BindRequest:
235                 return ldapsrv_BindRequest(call);
236         case LDAP_TAG_UnbindRequest:
237                 return ldapsrv_UnbindRequest(call);
238         case LDAP_TAG_SearchRequest:
239                 return ldapsrv_SearchRequest(call);
240         case LDAP_TAG_ModifyRequest:
241                 return ldapsrv_ModifyRequest(call);
242         case LDAP_TAG_AddRequest:
243                 return ldapsrv_AddRequest(call);
244         case LDAP_TAG_DelRequest:
245                 return ldapsrv_DelRequest(call);
246         case LDAP_TAG_ModifyDNRequest:
247                 return ldapsrv_ModifyDNRequest(call);
248         case LDAP_TAG_CompareRequest:
249                 return ldapsrv_CompareRequest(call);
250         case LDAP_TAG_AbandonRequest:
251                 return ldapsrv_AbandonRequest(call);
252         case LDAP_TAG_ExtendedRequest:
253                 return ldapsrv_ExtendedRequest(call);
254         default:
255                 return ldapsrv_unwilling(call, 2);
256         }
257 }