2 Unix SMB/CIFS implementation.
4 CLDAP server - rootdse handling
6 Copyright (C) Stefan Metzmacher 2006
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 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libcli/ldap/ldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "smbd/service_task.h"
28 #include "cldap_server/cldap_server.h"
29 #include "librpc/gen_ndr/ndr_misc.h"
30 #include "dsdb/samdb/samdb.h"
33 static void cldapd_rootdse_fill(struct cldapd_server
*cldapd
,
35 struct ldap_SearchRequest
*search
,
36 struct ldap_SearchResEntry
**response
,
37 struct ldap_Result
*result
)
39 struct ldap_SearchResEntry
*ent
= NULL
;
40 struct ldb_dn
*basedn
;
41 struct ldb_result
*res
= NULL
;
42 struct ldb_request
*lreq
;
43 enum ldb_scope scope
= LDB_SCOPE_DEFAULT
;
44 const char **attrs
= NULL
;
45 const char *errstr
= NULL
;
49 basedn
= ldb_dn_new(mem_ctx
, cldapd
->samctx
, NULL
);
50 if (basedn
== NULL
) goto nomem
;
51 scope
= LDB_SCOPE_BASE
;
53 if (search
->num_attributes
>= 1) {
56 attrs
= talloc_array(mem_ctx
, const char *, search
->num_attributes
+1);
57 if (attrs
== NULL
) goto nomem
;
59 for (i
=0; i
< search
->num_attributes
; i
++) {
60 attrs
[i
] = search
->attributes
[i
];
65 res
= talloc_zero(mem_ctx
, struct ldb_result
);
66 if (res
== NULL
) goto nomem
;
68 ldb_ret
= ldb_build_search_req_ex(&lreq
, cldapd
->samctx
, mem_ctx
,
72 res
, ldb_search_default_callback
,
75 if (ldb_ret
!= LDB_SUCCESS
) {
79 /* Copy the timeout from the incoming call */
80 ldb_set_timeout(cldapd
->samctx
, lreq
, search
->timelimit
);
82 ldb_ret
= ldb_request(cldapd
->samctx
, lreq
);
83 if (ldb_ret
!= LDB_SUCCESS
) {
87 ldb_ret
= ldb_wait(lreq
->handle
, LDB_WAIT_ALL
);
88 if (ldb_ret
!= LDB_SUCCESS
) {
93 errstr
= "Internal error: to much replies";
94 ldb_ret
= LDB_ERR_OTHER
;
96 } else if (res
->count
== 1) {
99 ent
= talloc(mem_ctx
, struct ldap_SearchResEntry
);
100 if (ent
== NULL
) goto nomem
;
102 ent
->dn
= ldb_dn_alloc_linearized(ent
, res
->msgs
[0]->dn
);
103 if (ent
->dn
== NULL
) goto nomem
;
104 ent
->num_attributes
= 0;
105 ent
->attributes
= NULL
;
106 if (res
->msgs
[0]->num_elements
== 0) {
109 ent
->num_attributes
= res
->msgs
[0]->num_elements
;
110 ent
->attributes
= talloc_array(ent
, struct ldb_message_element
, ent
->num_attributes
);
111 if (ent
->attributes
== NULL
) goto nomem
;
112 for (j
=0; j
< ent
->num_attributes
; j
++) {
113 ent
->attributes
[j
].name
= talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].name
);
114 ent
->attributes
[j
].num_values
= 0;
115 ent
->attributes
[j
].values
= NULL
;
116 if (search
->attributesonly
&& (res
->msgs
[0]->elements
[j
].num_values
== 0)) {
119 ent
->attributes
[j
].num_values
= res
->msgs
[0]->elements
[j
].num_values
;
120 ent
->attributes
[j
].values
= res
->msgs
[0]->elements
[j
].values
;
121 talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].values
);
128 } else if (ldb_ret
== LDB_SUCCESS
) {
133 errstr
= ldb_errstring(cldapd
->samctx
);
138 ret
= LDAP_OPERATIONS_ERROR
;
139 errstr
= "No memory";
142 result
->resultcode
= ret
;
143 result
->errormessage
= (errstr
?talloc_strdup(mem_ctx
, errstr
):NULL
);
147 handle incoming cldap requests
149 void cldapd_rootdse_request(struct cldap_socket
*cldap
,
150 struct cldapd_server
*cldapd
,
153 struct ldap_SearchRequest
*search
,
154 struct tsocket_address
*src
)
157 struct cldap_reply reply
;
158 struct ldap_Result result
;
162 reply
.messageid
= message_id
;
164 reply
.response
= NULL
;
165 reply
.result
= &result
;
167 cldapd_rootdse_fill(cldapd
, tmp_ctx
, search
, &reply
.response
, reply
.result
);
169 status
= cldap_reply_send(cldap
, &reply
);
170 if (!NT_STATUS_IS_OK(status
)) {
171 DEBUG(2,("cldap rootdse query failed '%s' - %s\n",
172 ldb_filter_from_tree(tmp_ctx
, search
->tree
), nt_errstr(status
)));