2 Samba CIFS implementation
3 ADS convenience functions for GPO
5 Copyright (C) 2001 Andrew Tridgell (from samba3 ads.c)
6 Copyright (C) 2001 Remus Koos (from samba3 ads.c)
7 Copyright (C) 2001 Andrew Bartlett (from samba3 ads.c)
8 Copyright (C) 2008 Jelmer Vernooij, jelmer@samba.org
9 Copyright (C) 2008 Wilco Baan Hofman, wilco@baanhofman.nl
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "libnet/libnet.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28 #include "libgpo/ads_convenience.h"
29 #include "param/param.h"
30 #include "libcli/libcli.h"
33 static ADS_STATUS
ads_connect(ADS_STRUCT
*ads
);
35 WERROR
ads_startup (struct libnet_context
*netctx
, ADS_STRUCT
**ads
)
37 *ads
= talloc(netctx
, ADS_STRUCT
);
38 (*ads
)->netctx
= netctx
;
45 static ADS_STATUS
ads_connect(ADS_STRUCT
*ads
)
47 struct libnet_LookupDCs
*io
;
50 io
= talloc_zero(ads
, struct libnet_LookupDCs
);
52 /* We are looking for the PDC of the active domain. */
53 io
->in
.name_type
= NBT_NAME_PDC
;
54 io
->in
.domain_name
= lp_workgroup(ads
->netctx
->lp_ctx
);
55 libnet_LookupDCs(ads
->netctx
, ads
, io
);
57 url
= talloc_asprintf(ads
, "ldap://%s", io
->out
.dcs
[0].name
);
58 ads
->ldbctx
= ldb_wrap_connect(ads
, ads
->netctx
->event_ctx
, ads
->netctx
->lp_ctx
,
59 url
, NULL
, ads
->netctx
->cred
, 0, NULL
);
60 if (ads
->ldbctx
== NULL
) {
61 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
64 return ADS_ERROR_NT(NT_STATUS_OK
);
67 ADS_STATUS
ads_search_dn(ADS_STRUCT
*ads
, LDAPMessage
**res
,
68 const char *dn
, const char **attrs
)
72 status
.err
.rc
= ldb_search(ads
->ldbctx
, ads
, res
,
73 ldb_dn_new(ads
, ads
->ldbctx
, dn
),
78 status
.error_type
= ENUM_ADS_ERROR_LDAP
;
82 const char * ads_get_dn(ADS_STRUCT
*ads
, LDAPMessage
*res
)
84 return ldb_dn_get_linearized(res
->msgs
[0]->dn
);
87 bool ads_pull_sd(ADS_STRUCT
*ads
, TALLOC_CTX
*ctx
, LDAPMessage
*res
, const char *field
, struct security_descriptor
**sd
)
89 const struct ldb_val
*val
;
90 enum ndr_err_code ndr_err
;
92 val
= ldb_msg_find_ldb_val(res
->msgs
[0], field
);
94 *sd
= talloc(ctx
, struct security_descriptor
);
98 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
99 ndr_err
= ndr_pull_struct_blob(val
, *sd
, NULL
, *sd
,
100 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
101 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
108 ADS_STATUS
ads_search_retry_dn_sd_flags(ADS_STRUCT
*ads
, LDAPMessage
**res
, uint32_t sd_flags
,
109 const char *dn
, const char **attrs
)
111 return ads_do_search_all_sd_flags(ads
, dn
, LDB_SCOPE_BASE
, "(objectclass=*)", attrs
, sd_flags
, res
);
114 ADS_STATUS
ads_do_search_all_sd_flags (ADS_STRUCT
*ads
, const char *dn
, int scope
,
115 const char *filter
, const char **attrs
,
116 uint32_t sd_flags
, LDAPMessage
**res
)
119 struct ldb_request
*req
;
120 struct ldb_control
**controls
;
121 struct ldb_parse_tree
*tree
;
122 struct ldb_dn
*ldb_dn
;
124 controls
= talloc_zero_array(ads
, struct ldb_control
*, 2);
125 controls
[0] = talloc(ads
, struct ldb_control
);
126 controls
[0]->oid
= LDB_CONTROL_SD_FLAGS_OID
;
127 controls
[0]->data
= &sd_flags
;
128 controls
[0]->critical
= 1;
130 tree
= ldb_parse_tree(ads
, filter
);
132 ldb_dn
= ldb_dn_new(ads
, ads
->ldbctx
, dn
);
134 rv
= ldb_build_search_req_ex(&req
, ads
->ldbctx
, (TALLOC_CTX
*)res
, ldb_dn
, scope
, tree
, attrs
, controls
,
135 res
, ldb_search_default_callback
, NULL
);
136 if (rv
!= LDB_SUCCESS
) {
140 return ADS_ERROR(rv
);
142 rv
= ldb_request(ads
->ldbctx
, req
);
143 if (rv
== LDB_SUCCESS
) {
144 rv
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
149 return ADS_ERROR(rv
);
153 const char * ads_pull_string(ADS_STRUCT
*ads
, TALLOC_CTX
*ctx
, LDAPMessage
*res
, const char *field
)
155 return ldb_msg_find_attr_as_string(res
->msgs
[0], field
, NULL
);
158 bool ads_pull_uint32(ADS_STRUCT
*ads
, LDAPMessage
*res
, const char *field
, uint32_t *ret
)
160 if (ldb_msg_find_element(res
->msgs
[0], field
) == NULL
) {
163 *ret
= ldb_msg_find_attr_as_uint(res
->msgs
[0], field
, 0);
168 int ads_count_replies(ADS_STRUCT
*ads
, LDAPMessage
*res
)
173 ADS_STATUS
ads_msgfree(ADS_STRUCT
*ads
, LDAPMessage
*res
)
176 return ADS_ERROR_NT(NT_STATUS_OK
);
180 do a rough conversion between ads error codes and NT status codes
181 we'll need to fill this in more
183 NTSTATUS
ads_ntstatus(ADS_STATUS status
)
185 switch (status
.error_type
) {
186 case ENUM_ADS_ERROR_NT
:
187 return status
.err
.nt_status
;
188 case ENUM_ADS_ERROR_SYSTEM
:
189 return map_nt_error_from_unix(status
.err
.rc
);
190 case ENUM_ADS_ERROR_LDAP
:
191 if (status
.err
.rc
== LDB_SUCCESS
) {
194 return NT_STATUS_UNSUCCESSFUL
;
199 if (ADS_ERR_OK(status
)) {
202 return NT_STATUS_UNSUCCESSFUL
;
206 return a string for an error from an ads routine
208 const char *ads_errstr(ADS_STATUS status
)
210 switch (status
.error_type
) {
211 case ENUM_ADS_ERROR_SYSTEM
:
212 return strerror(status
.err
.rc
);
213 case ENUM_ADS_ERROR_LDAP
:
214 return ldb_strerror(status
.err
.rc
);
215 case ENUM_ADS_ERROR_NT
:
216 return get_friendly_nt_error_msg(ads_ntstatus(status
));
218 return "Unknown ADS error type!? (not compiled in?)";
222 ADS_STATUS
ads_build_ldap_error(int ldb_error
)
225 ret
.err
.rc
= ldb_error
;
226 ret
.error_type
= ENUM_ADS_ERROR_LDAP
;
230 ADS_STATUS
ads_build_nt_error(NTSTATUS nt_status
)
233 ret
.err
.nt_status
= nt_status
;
234 ret
.error_type
= ENUM_ADS_ERROR_NT
;
239 bool nt_token_check_sid( const struct dom_sid
*sid
, const NT_USER_TOKEN
*token
)
243 if (!sid
|| !token
) {
247 if (dom_sid_equal(sid
, token
->user_sid
)) {
250 if (dom_sid_equal(sid
, token
->group_sid
)) {
253 for (i
= 0; i
< token
->num_sids
; i
++) {
254 if (dom_sid_equal(sid
, token
->sids
[i
])) {
261 const char *ads_get_ldap_server_name(ADS_STRUCT
*ads
) {
262 return ads
->ldap_server_name
;
268 Stub write functions, these do not do anything, though they should. -- Wilco
271 ADS_MODLIST
ads_init_mods(TALLOC_CTX
*ctx
)
276 ADS_STATUS
ads_mod_str(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
, const char *name
, const char *val
)
278 return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED
);
281 ADS_STATUS
ads_gen_mod(ADS_STRUCT
*ads
, const char *mod_dn
, ADS_MODLIST mods
)
283 return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED
);