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/>.
23 #include "libcli/ldap/ldap.h"
24 #include "lib/ldb/include/ldb.h"
25 #include "lib/ldb/include/ldb_errors.h"
26 #include "lib/events/events.h"
27 #include "lib/socket/socket.h"
28 #include "smbd/service_task.h"
29 #include "cldap_server/cldap_server.h"
30 #include "librpc/gen_ndr/ndr_misc.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "auth/auth.h"
34 #include "system/network.h"
35 #include "lib/socket/netif.h"
37 static void cldapd_rootdse_fill(struct cldapd_server
*cldapd
,
39 struct ldap_SearchRequest
*search
,
40 struct ldap_SearchResEntry
**response
,
41 struct ldap_Result
*result
)
43 struct ldap_SearchResEntry
*ent
= NULL
;
44 struct ldb_dn
*basedn
;
45 struct ldb_result
*res
= NULL
;
46 struct ldb_request
*lreq
;
47 enum ldb_scope scope
= LDB_SCOPE_DEFAULT
;
48 const char **attrs
= NULL
;
49 const char *errstr
= NULL
;
53 basedn
= ldb_dn_new(mem_ctx
, cldapd
->samctx
, NULL
);
54 if (basedn
== NULL
) goto nomem
;
55 scope
= LDB_SCOPE_BASE
;
57 if (search
->num_attributes
>= 1) {
60 attrs
= talloc_array(mem_ctx
, const char *, search
->num_attributes
+1);
61 if (attrs
== NULL
) goto nomem
;
63 for (i
=0; i
< search
->num_attributes
; i
++) {
64 attrs
[i
] = search
->attributes
[i
];
69 res
= talloc_zero(mem_ctx
, struct ldb_result
);
70 if (res
== NULL
) goto nomem
;
72 ldb_ret
= ldb_build_search_req_ex(&lreq
, cldapd
->samctx
, mem_ctx
,
76 res
, ldb_search_default_callback
,
79 if (ldb_ret
!= LDB_SUCCESS
) {
83 /* Copy the timeout from the incoming call */
84 ldb_set_timeout(cldapd
->samctx
, lreq
, search
->timelimit
);
86 ldb_ret
= ldb_request(cldapd
->samctx
, lreq
);
87 if (ldb_ret
!= LDB_SUCCESS
) {
91 ldb_ret
= ldb_wait(lreq
->handle
, LDB_WAIT_ALL
);
92 if (ldb_ret
!= LDB_SUCCESS
) {
97 errstr
= "Internal error: to much replies";
98 ldb_ret
= LDB_ERR_OTHER
;
100 } else if (res
->count
== 1) {
103 ent
= talloc(mem_ctx
, struct ldap_SearchResEntry
);
104 if (ent
== NULL
) goto nomem
;
106 ent
->dn
= ldb_dn_alloc_linearized(ent
, res
->msgs
[0]->dn
);
107 if (ent
->dn
== NULL
) goto nomem
;
108 ent
->num_attributes
= 0;
109 ent
->attributes
= NULL
;
110 if (res
->msgs
[0]->num_elements
== 0) {
113 ent
->num_attributes
= res
->msgs
[0]->num_elements
;
114 ent
->attributes
= talloc_array(ent
, struct ldb_message_element
, ent
->num_attributes
);
115 if (ent
->attributes
== NULL
) goto nomem
;
116 for (j
=0; j
< ent
->num_attributes
; j
++) {
117 ent
->attributes
[j
].name
= talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].name
);
118 ent
->attributes
[j
].num_values
= 0;
119 ent
->attributes
[j
].values
= NULL
;
120 if (search
->attributesonly
&& (res
->msgs
[0]->elements
[j
].num_values
== 0)) {
123 ent
->attributes
[j
].num_values
= res
->msgs
[0]->elements
[j
].num_values
;
124 ent
->attributes
[j
].values
= res
->msgs
[0]->elements
[j
].values
;
125 talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].values
);
132 } else if (ldb_ret
== LDB_SUCCESS
) {
137 errstr
= ldb_errstring(cldapd
->samctx
);
142 ret
= LDAP_OPERATIONS_ERROR
;
143 errstr
= "No memory";
146 result
->resultcode
= ret
;
147 result
->errormessage
= (errstr
?talloc_strdup(mem_ctx
, errstr
):NULL
);
151 handle incoming cldap requests
153 void cldapd_rootdse_request(struct cldap_socket
*cldap
,
155 struct ldap_SearchRequest
*search
,
156 struct socket_address
*src
)
158 struct cldapd_server
*cldapd
= talloc_get_type(cldap
->incoming
.private, struct cldapd_server
);
160 struct cldap_reply reply
;
161 struct ldap_Result result
;
162 TALLOC_CTX
*tmp_ctx
= talloc_new(cldap
);
166 reply
.messageid
= message_id
;
168 reply
.response
= NULL
;
169 reply
.result
= &result
;
171 cldapd_rootdse_fill(cldapd
, tmp_ctx
, search
, &reply
.response
, reply
.result
);
173 status
= cldap_reply_send(cldap
, &reply
);
174 if (!NT_STATUS_IS_OK(status
)) {
175 DEBUG(2,("cldap rootdse query failed '%s' - %s\n",
176 ldb_filter_from_tree(tmp_ctx
, search
->tree
), nt_errstr(status
)));
179 talloc_free(tmp_ctx
);