1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "ldap.h"
30
31 #include <time.h>
32 #include <limits.h>
33
34 #include "../util/util.h"
35
36 static int get_ldap_scope(
const char *str) {
37
38 if(!strcmp(str,
"base")) {
39 return LDAP_SCOPE_BASE;
40 }
else if(!strcmp(str,
"onelevel")) {
41 return LDAP_SCOPE_ONELEVEL;
42 }
else if(!strcmp(str,
"subtree")) {
43 return LDAP_SCOPE_SUBTREE;
44 }
else if(!strcmp(str,
"children")) {
45 return LDAP_SCOPE_CHILDREN;
46 }
47 return -
1;
48 }
49
50 int service_ldap_search(pblock *pb, Session *sn, Request *rq) {
51 char *resource_name = pblock_findval(
"resource", pb);
52 char *basedn = pblock_findval(
"basedn", pb);
53 char *binddn = pblock_findval(
"bindnd", pb);
54 char *bindpw = pblock_findval(
"bindpw", pb);
55 char *filter = pblock_findval(
"filter", pb);
56 char *empty_query_error = pblock_findval(
"empty_filter_error", pb);
57 char *empty_result_error = pblock_findval(
"empty_result_error", pb);
58 char *scope_str = pblock_findval(
"scope", pb);
59 char *timeout_str = pblock_findval(
"timeout", pb);
60 char *sizelimit_str = pblock_findval(
"sizelimit", pb);
61
62 int status_empty_filter =
WS_SAFS_LDAP_EMPTY_FILTER_ERROR;
63 int status_empty_result =
WS_SAFS_LDAP_EMPTY_RESULT_ERROR;
64
65 if(empty_query_error) {
66 int64_t status =
0;
67 util_strtoint(empty_query_error, &status);
68 if(status <
200 || status >
999) {
69 log_ereport(
LOG_MISCONFIG,
"ldap-search: empty_query_error parameter must be an integer between 200 and 999");
70 return REQ_ABORTED;
71 }
72 status_empty_filter = status;
73 }
74 if(empty_result_error) {
75 int64_t status =
0;
76 util_strtoint(empty_result_error, &status);
77 if(status <
200 || status >
999) {
78 log_ereport(
LOG_MISCONFIG,
"ldap-search: empty_result_error parameter must be an integer between 200 and 999");
79 return REQ_ABORTED;
80 }
81 status_empty_result = status;
82 }
83
84
85
86 WSBool empty_query_response = status_empty_filter <
300 ?
TRUE :
FALSE;
87 WSBool empty_result_response = status_empty_result <
300 ?
TRUE :
FALSE;
88
89 int scope =
WS_SAFS_LDAP_DEFAULT_SCOPE;
90 if(scope_str) {
91 scope = get_ldap_scope(scope_str);
92 if(scope <
0) {
93 log_ereport(
LOG_MISCONFIG,
"ldap-search: unknown scope %s", scope_str);
94 return REQ_ABORTED;
95 }
96 }
97 int timeout =
WS_SAFS_LDAP_DEFAULT_TIMEOUT;
98 if(timeout_str) {
99 int64_t t;
100 if(util_strtoint(timeout_str, &t)) {
101 if(t <
0 || t >
WS_SAFS_LDAP_MAX_TIMEOUT) {
102 log_ereport(
LOG_MISCONFIG,
"ldap-search: timeout out of range");
103 return REQ_ABORTED;
104 }
105 timeout = t;
106 }
else {
107 log_ereport(
LOG_MISCONFIG,
"ldap-search: timeout %s is not a number", timeout_str);
108 }
109 }
110 int sizelimit =
WS_SAFS_LDAP_DEFAULT_SIZELIMIT;
111 if(sizelimit_str) {
112 int64_t v;
113 if(util_strtoint(sizelimit_str, &v)) {
114 if(v >
INT_MAX) {
115 log_ereport(
LOG_MISCONFIG,
"ldap-search: sizelimit out of range");
116 return REQ_ABORTED;
117 }
118 sizelimit = v;
119 }
else {
120 log_ereport(
LOG_MISCONFIG,
"ldap-search: sizelimit %s is not a number", timeout_str);
121 }
122 }
123
124
125 if(!resource_name) {
126 log_ereport(
LOG_MISCONFIG,
"ldap-search: missing resource parameter");
127 return REQ_ABORTED;
128 }
129 if(!basedn) {
130 log_ereport(
LOG_MISCONFIG,
"ldap-search: missing basedn parameter");
131 return REQ_ABORTED;
132 }
133
134 if(!filter) {
135
136 filter = pblock_findval(
"ldap_filter", rq->vars);
137 log_ereport(
LOG_DEBUG,
"ldap-search: no filter parameter, rq.vars ldap_filter: %s", filter);
138 if(!filter) {
139
140 protocol_status(sn, rq, status_empty_filter,
NULL);
141 if(empty_query_response) {
142 pblock_nvinsert(
"content-length",
"0", rq->srvhdrs);
143 http_start_response(sn, rq);
144 }
else {
145 log_ereport(
LOG_FAILURE,
"ldap-search: no filter specified");
146 }
147 return REQ_PROCEED;
148 }
149 }
150
151
152 ResourceData *resdata = resourcepool_lookup(sn, rq, resource_name,
0);
153 if(!resdata) {
154 log_ereport(
LOG_FAILURE,
"ldap-search: cannot get resource %s", resource_name);
155 return REQ_ABORTED;
156 }
157 LDAP *ldap = resdata->data;
158
159
160 if(binddn) {
161 struct berval *server_cred;
162 if(ws_ldap_bind(ldap, binddn, bindpw ? bindpw :
"", &server_cred) !=
LDAP_SUCCESS) {
163 log_ereport(
LOG_FAILURE,
"ldap-search: resource %s: cannot bind %s", resource_name, binddn);
164 resourcepool_free(sn, rq, resdata);
165 return REQ_ABORTED;
166 }
167 }
168
169
170
171 LDAPMessage *result;
172 struct timeval ts;
173 ts.tv_sec = timeout;
174 ts.tv_usec =
0;
175 int r = ldap_search_ext_s(
176 ldap,
177 basedn,
178 LDAP_SCOPE_SUBTREE,
179 filter,
180 NULL,
181 0,
182 NULL,
183 NULL,
184 &ts,
185 sizelimit,
186 &result);
187
188 if(r !=
LDAP_SUCCESS) {
189 if(result) {
190 ldap_msgfree(result);
191 }
192 log_ereport(
LOG_FAILURE,
"ldap-search: ldap error: %s", ldap_err2string(r));
193 return REQ_ABORTED;
194 }
195
196
197
198 protocol_status(sn, rq,
200,
NULL);
199
200
201 LDAPMessage *msg = ldap_first_entry(ldap, result);
202 if(!msg) {
203 protocol_status(sn, rq, status_empty_result,
NULL);
204 if(empty_result_response) {
205 pblock_nvinsert(
"content-length",
"0", rq->srvhdrs);
206 }
207 }
else {
208 protocol_status(sn, rq,
200,
NULL);
209 }
210 http_start_response(sn, rq);
211
212 while(msg) {
213
214 char *dn = ldap_get_dn(ldap, msg);
215 if(dn) {
216 net_printf(sn->csd,
"dn: %s\n", dn);
217 ldap_memfree(dn);
218 }
219
220
221 BerElement *ber =
NULL;
222 char *attribute = attribute=ldap_first_attribute(ldap, msg, &ber);
223 while(attribute !=
NULL) {
224 struct berval **values = ldap_get_values_len(ldap, msg, attribute);
225 if(values) {
226 int count = ldap_count_values_len(values);
227 for(
int i=
0;i<count;i++) {
228 cxstring value = cx_strn(values[i]->bv_val, values[i]->bv_len);
229 net_printf(sn->csd,
"%s: %.*s\n", attribute, (
int)value.length, value.ptr);
230 }
231 ldap_value_free_len(values);
232 }
233 ldap_memfree(attribute);
234 attribute = ldap_next_attribute(ldap, msg, ber);
235 }
236 if(ber) {
237 ber_free(ber,
0);
238 }
239 net_printf(sn->csd,
"\n");
240 msg = ldap_next_entry(ldap, msg);
241 }
242 ldap_msgfree(result);
243
244
245 return REQ_PROCEED;
246 }
247