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/>.
25 #include <ldb_errors.h>
26 #include "smbd/service_task.h"
27 #include "cldap_server/cldap_server.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "dsdb/samdb/samdb.h"
32 static void cldapd_rootdse_fill(struct cldapd_server
*cldapd
,
34 struct ldap_SearchRequest
*search
,
35 struct ldap_SearchResEntry
**response
,
36 struct ldap_Result
*result
)
38 struct ldap_SearchResEntry
*ent
= NULL
;
39 struct ldb_result
*res
= NULL
;
40 struct ldb_request
*lreq
;
41 const char **attrs
= NULL
;
42 const char *errstr
= NULL
;
43 int ret
= LDAP_SUCCESS
, ldb_ret
;
45 if (search
->num_attributes
>= 1) {
48 attrs
= talloc_array(mem_ctx
, const char *, search
->num_attributes
+1);
49 if (attrs
== NULL
) goto nomem
;
51 for (i
=0; i
< search
->num_attributes
; i
++) {
52 attrs
[i
] = search
->attributes
[i
];
57 res
= talloc_zero(mem_ctx
, struct ldb_result
);
58 if (res
== NULL
) goto nomem
;
60 ldb_ret
= ldb_build_search_req_ex(&lreq
, cldapd
->samctx
, mem_ctx
,
64 res
, ldb_search_default_callback
,
67 if (ldb_ret
!= LDB_SUCCESS
) {
71 /* Copy the timeout from the incoming call */
72 ldb_set_timeout(cldapd
->samctx
, lreq
, search
->timelimit
);
74 ldb_ret
= ldb_request(cldapd
->samctx
, lreq
);
75 if (ldb_ret
!= LDB_SUCCESS
) {
79 ldb_ret
= ldb_wait(lreq
->handle
, LDB_WAIT_ALL
);
80 if (ldb_ret
!= LDB_SUCCESS
) {
85 errstr
= "Internal error: to much replies";
86 ldb_ret
= LDB_ERR_OTHER
;
88 } else if (res
->count
== 1) {
91 ent
= talloc(mem_ctx
, struct ldap_SearchResEntry
);
92 if (ent
== NULL
) goto nomem
;
94 ent
->dn
= ldb_dn_alloc_linearized(ent
, res
->msgs
[0]->dn
);
95 if (ent
->dn
== NULL
) goto nomem
;
96 ent
->num_attributes
= 0;
97 ent
->attributes
= NULL
;
98 if (res
->msgs
[0]->num_elements
== 0) {
101 ent
->num_attributes
= res
->msgs
[0]->num_elements
;
102 ent
->attributes
= talloc_array(ent
, struct ldb_message_element
,
103 ent
->num_attributes
);
104 if (ent
->attributes
== NULL
) goto nomem
;
105 for (j
=0; j
< ent
->num_attributes
; j
++) {
106 ent
->attributes
[j
].name
= talloc_steal(ent
->attributes
,
107 res
->msgs
[0]->elements
[j
].name
);
108 ent
->attributes
[j
].num_values
= 0;
109 ent
->attributes
[j
].values
= NULL
;
110 if (search
->attributesonly
&& (res
->msgs
[0]->elements
[j
].num_values
== 0)) {
113 ent
->attributes
[j
].num_values
= res
->msgs
[0]->elements
[j
].num_values
;
114 ent
->attributes
[j
].values
= res
->msgs
[0]->elements
[j
].values
;
115 talloc_steal(ent
->attributes
, res
->msgs
[0]->elements
[j
].values
);
120 if (ret
!= LDAP_SUCCESS
) {
122 } else if (ldb_ret
== LDB_SUCCESS
) {
127 errstr
= ldb_errstring(cldapd
->samctx
);
132 ret
= LDAP_OPERATIONS_ERROR
;
133 errstr
= "No memory";
136 result
->resultcode
= ret
;
137 result
->errormessage
= (errstr
?talloc_strdup(mem_ctx
, errstr
):NULL
);
141 handle incoming cldap requests
143 void cldapd_rootdse_request(struct cldap_socket
*cldap
,
144 struct cldapd_server
*cldapd
,
147 struct ldap_SearchRequest
*search
,
148 struct tsocket_address
*src
)
151 struct cldap_reply reply
;
152 struct ldap_Result result
;
156 reply
.messageid
= message_id
;
158 reply
.response
= NULL
;
159 reply
.result
= &result
;
161 /* Note: The remoteAddress should rather be set on a ldb request.
162 * We can set this savely on the context here,
163 * since cldapd_rootdse_fill operates synchronously. */
164 ldb_set_opaque(cldapd
->samctx
, "remoteAddress", src
);
166 cldapd_rootdse_fill(cldapd
, tmp_ctx
, search
, &reply
.response
,
170 * We clear this after cldapd_rootdse_fill as this is shared ldb
171 * and if it was not cleared the audit logging would report changes
172 * made by internal processes as coming from the last cldap requester
174 ldb_set_opaque(cldapd
->samctx
, "remoteAddress", NULL
);
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
)));