r2688: - fix case where listed attributes are asked
[bbaumbach/samba-autobuild/.git] / source4 / ldap_server / ldap_simple_ldb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP server SIMPLE LDB implementation
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
23 /* TODO: samdb_context is not a pulblic struct */
24 struct samdb_context {
25         struct ldb_context *ldb;
26         struct samdb_context **static_ptr;
27 };
28
29
30 #define ALLOC_CHECK(ptr) do {\
31         if (!(ptr)) {\
32                 return NT_STATUS_NO_MEMORY;\
33         }\
34 } while(0)
35
36 static NTSTATUS sldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
37                                      struct ldap_SearchRequest *r)
38 {
39         NTSTATUS status;
40         struct ldap_Result *done;
41         struct ldap_SearchResEntry *ent;
42         struct ldapsrv_reply *ent_r, *done_r;
43         int result = 80;
44         struct samdb_context *samdb;
45         struct ldb_message **res;
46         int i, j, y, count;
47         struct ldb_context *ldb;
48         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
49         const char **attrs = NULL;
50
51         DEBUG(0, ("sldb_Search: %s\n", r->filter));
52
53         samdb = samdb_connect(call);
54         ldb = samdb->ldb;
55
56         switch (r->scope) {
57                 case LDAP_SEARCH_SCOPE_BASE:
58                         scope = LDB_SCOPE_BASE;
59                         break;
60                 case LDAP_SEARCH_SCOPE_SINGLE:
61                         scope = LDB_SCOPE_ONELEVEL;
62                         break;
63                 case LDAP_SEARCH_SCOPE_SUB:
64                         scope = LDB_SCOPE_SUBTREE;
65                         break;
66         }
67
68         if (r->num_attributes >= 1) {
69                 attrs = talloc_array_p(samdb, const char *, r->num_attributes+1);
70                 ALLOC_CHECK(attrs);
71
72                 for (i=0; i < r->num_attributes; i++) {
73                         attrs[i] = r->attributes[i];
74                 }
75                 attrs[i] = NULL;
76         }
77
78         ldb_set_alloc(ldb, talloc_ldb_alloc, samdb);
79         count = ldb_search(ldb, r->basedn, scope, r->filter, attrs, &res);
80
81         if (count > 0) {
82                 result = 0;
83         } else if (count == 0) {
84                 result = 32;
85         } else if (count == -1) {
86                 result = 1;
87         }
88
89         for (i=0; i < count; i++) {
90                 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
91                 ALLOC_CHECK(ent_r);
92
93                 ent = &ent_r->msg.r.SearchResultEntry;
94                 ent->dn = talloc_steal(ent_r, res[i]->dn);
95                 ent->num_attributes = 0;
96                 ent->attributes = NULL;
97                 if (res[i]->num_elements == 0) {
98                         continue;
99                 }
100                 ent->num_attributes = res[i]->num_elements;
101                 ent->attributes = talloc_array_p(ent_r, struct ldap_attribute, ent->num_attributes);
102                 ALLOC_CHECK(ent->attributes);
103                 for (j=0; j < ent->num_attributes; j++) {
104                         ent->attributes[j].name = talloc_steal(ent->attributes, res[i]->elements[j].name);
105                         ent->attributes[j].num_values = 0;
106                         ent->attributes[j].values = NULL;
107                         if (r->attributesonly && (res[i]->elements[j].num_values == 0)) {
108                                 continue;
109                         }
110                         ent->attributes[j].num_values = res[i]->elements[j].num_values;
111                         ent->attributes[j].values = talloc_array_p(ent->attributes,
112                                                         DATA_BLOB, ent->attributes[j].num_values);
113                         ALLOC_CHECK(ent->attributes[j].values);
114                         for (y=0; y < ent->attributes[j].num_values; y++) {
115                                 ent->attributes[j].values[y].length = res[i]->elements[j].values[y].length;
116                                 ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values,
117                                                                         res[i]->elements[j].values[y].data);
118                         }
119                 }
120
121                 status = ldapsrv_queue_reply(call, ent_r);
122                 if (!NT_STATUS_IS_OK(status)) {
123                         return status;
124                 }
125         }
126
127         talloc_free(samdb);
128
129         done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
130         ALLOC_CHECK(done_r);
131
132         done = &done_r->msg.r.SearchResultDone;
133         done->resultcode = result;
134         done->dn = NULL;
135         done->errormessage = NULL;
136         done->referral = NULL;
137
138         return ldapsrv_queue_reply(call, done_r);
139 }
140
141 static const struct ldapsrv_partition_ops sldb_ops = {
142         .Search         = sldb_Search
143 };
144
145 const struct ldapsrv_partition_ops *ldapsrv_get_sldb_partition_ops(void)
146 {
147         return &sldb_ops;
148 }