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 lreq
= talloc(mem_ctx
, struct ldb_request
);
70 if (lreq
== NULL
) goto nomem
;
72 res
= talloc_zero(mem_ctx
, struct ldb_result
);
73 if (res
== NULL
) goto nomem
;
75 lreq
->operation
= LDB_SEARCH
;
76 lreq
->op
.search
.base
= basedn
;
77 lreq
->op
.search
.scope
= scope
;
78 lreq
->op
.search
.tree
= search
->tree
;
79 lreq
->op
.search
.attrs
= attrs
;
81 lreq
->controls
= NULL
;
84 lreq
->callback
= ldb_search_default_callback
;
86 /* Copy the timeout from the incoming call */
87 ldb_set_timeout(cldapd
->samctx
, lreq
, search
->timelimit
);
89 ldb_ret
= ldb_request(cldapd
->samctx
, lreq
);
90 if (ldb_ret
!= LDB_SUCCESS
) {
94 ldb_ret
= ldb_wait(lreq
->handle
, LDB_WAIT_ALL
);
95 if (ldb_ret
!= LDB_SUCCESS
) {
100 errstr
= "Internal error: to much replies";
101 ldb_ret
= LDB_ERR_OTHER
;
103 } else if (res
->count
== 1) {
106 ent
= talloc(mem_ctx
, struct ldap_SearchResEntry
);
107 if (ent
== NULL
) goto nomem
;
109 ent
->dn
= ldb_dn_alloc_linearized(ent
, res
->msgs
[0]->dn
);
110 if (ent
->dn
== NULL
) goto nomem
;
111 ent
->num_attributes
= 0;
112 ent
->attributes
= NULL
;
113 if (res
->msgs
[0]->num_elements
== 0) {
116 ent
->num_attributes
= res
->msgs
[0]->num_elements
;
117 ent
->attributes
= talloc_array(ent
, struct ldb_message_element
, ent
->num_attributes
);
118 if (ent
->attributes
== NULL
) goto nomem
;
119 for (j
=0; j
< ent
->num_attributes
; j
++) {
120 ent
->attributes
[j
].name
= talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].name
);
121 ent
->attributes
[j
].num_values
= 0;
122 ent
->attributes
[j
].values
= NULL
;
123 if (search
->attributesonly
&& (res
->msgs
[0]->elements
[j
].num_values
== 0)) {
126 ent
->attributes
[j
].num_values
= res
->msgs
[0]->elements
[j
].num_values
;
127 ent
->attributes
[j
].values
= res
->msgs
[0]->elements
[j
].values
;
128 talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].values
);
135 } else if (ldb_ret
== LDB_SUCCESS
) {
140 errstr
= ldb_errstring(cldapd
->samctx
);
145 ret
= LDAP_OPERATIONS_ERROR
;
146 errstr
= "No memory";
149 result
->resultcode
= ret
;
150 result
->errormessage
= (errstr
?talloc_strdup(mem_ctx
, errstr
):NULL
);
154 handle incoming cldap requests
156 void cldapd_rootdse_request(struct cldap_socket
*cldap
,
158 struct ldap_SearchRequest
*search
,
159 struct socket_address
*src
)
161 struct cldapd_server
*cldapd
= talloc_get_type(cldap
->incoming
.private, struct cldapd_server
);
163 struct cldap_reply reply
;
164 struct ldap_Result result
;
165 TALLOC_CTX
*tmp_ctx
= talloc_new(cldap
);
169 reply
.messageid
= message_id
;
171 reply
.response
= NULL
;
172 reply
.result
= &result
;
174 cldapd_rootdse_fill(cldapd
, tmp_ctx
, search
, &reply
.response
, reply
.result
);
176 status
= cldap_reply_send(cldap
, &reply
);
177 if (!NT_STATUS_IS_OK(status
)) {
178 DEBUG(2,("cldap rootdse query failed '%s' - %s\n",
179 ldb_filter_from_tree(tmp_ctx
, search
->tree
), nt_errstr(status
)));
182 talloc_free(tmp_ctx
);