e168cb5e0e62e4770a6d9a6603472d4fa3488fa2
[jra/samba/.git] / source4 / libgpo / ads_convenience.c
1 /*
2    Samba CIFS implementation
3    ADS convenience functions for GPO
4
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
10
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.
15
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.
20
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/>.
23 */
24
25 #include "includes.h"
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"
31 #include "ldb_wrap.h"
32
33 static ADS_STATUS ads_connect(ADS_STRUCT *ads);
34
35 WERROR ads_startup (struct libnet_context *netctx, ADS_STRUCT **ads)
36 {
37         *ads = talloc(netctx, ADS_STRUCT);
38         (*ads)->netctx = netctx;
39
40         ads_connect(*ads);
41
42         return WERR_OK;
43 }
44
45 static ADS_STATUS ads_connect(ADS_STRUCT *ads)
46 {
47         struct libnet_LookupDCs *io;
48         char *url;
49
50         io = talloc_zero(ads, struct libnet_LookupDCs);
51
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);
56
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);
62         }
63
64         return ADS_ERROR_NT(NT_STATUS_OK);
65 }
66
67 ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
68                          const char *dn, const char **attrs)
69 {
70         ADS_STATUS status;
71
72         status.err.rc = ldb_search(ads->ldbctx, ads, res,
73                                       ldb_dn_new(ads, ads->ldbctx, dn),
74                                       LDB_SCOPE_BASE,
75                                       attrs,
76                                       "(objectclass=*)");
77
78         status.error_type = ENUM_ADS_ERROR_LDAP;
79         return status;
80 }
81
82 const char * ads_get_dn(ADS_STRUCT *ads, LDAPMessage *res)
83 {
84         return ldb_dn_get_linearized(res->msgs[0]->dn);
85 }
86
87 bool ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *ctx, LDAPMessage *res, const char *field, struct security_descriptor **sd)
88 {
89         const struct ldb_val *val;
90         enum ndr_err_code ndr_err;
91
92         val = ldb_msg_find_ldb_val(res->msgs[0], field);
93
94         *sd = talloc(ctx, struct security_descriptor);
95         if (*sd == NULL) {
96                 return -1;
97         }
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)) {
102                 talloc_free(*sd);
103                 return -1;
104         }
105         return 0;
106 }
107
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)
110 {
111         return ads_do_search_all_sd_flags(ads, dn, LDB_SCOPE_BASE, "(objectclass=*)", attrs, sd_flags, res);
112 }
113
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)
117 {
118         int rv;
119         struct ldb_request *req;
120         struct ldb_control **controls;
121         struct ldb_parse_tree *tree;
122         struct ldb_dn *ldb_dn;
123
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;
129
130         tree = ldb_parse_tree(ads, filter);
131
132         ldb_dn = ldb_dn_new(ads, ads->ldbctx, dn);
133
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) {
137                 talloc_free(*res);
138                 talloc_free(req);
139                 talloc_free(tree);
140                 return ADS_ERROR(rv);
141         }
142         rv = ldb_request(ads->ldbctx, req);
143         if (rv == LDB_SUCCESS) {
144                 rv = ldb_wait(req->handle, LDB_WAIT_ALL);
145         }
146
147         talloc_free(req);
148         talloc_free(tree);
149         return ADS_ERROR(rv);
150
151 }
152
153 const char * ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *ctx, LDAPMessage *res, const char *field)
154 {
155         return ldb_msg_find_attr_as_string(res->msgs[0], field, NULL);
156 }
157
158 bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *res, const char *field, uint32_t *ret)
159 {
160         if (ldb_msg_find_element(res->msgs[0], field) == NULL) {
161                 return false;
162         }
163         *ret = ldb_msg_find_attr_as_uint(res->msgs[0], field, 0);
164         return true;
165 }
166
167
168 int ads_count_replies(ADS_STRUCT *ads, LDAPMessage *res)
169 {
170         return res->count;
171 }
172
173 ADS_STATUS ads_msgfree(ADS_STRUCT *ads, LDAPMessage *res)
174 {
175         talloc_free(res);
176         return ADS_ERROR_NT(NT_STATUS_OK);
177 }
178
179 /*
180   do a rough conversion between ads error codes and NT status codes
181   we'll need to fill this in more
182 */
183 NTSTATUS ads_ntstatus(ADS_STATUS status)
184 {
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) {
192                         return NT_STATUS_OK;
193                 }
194                 return NT_STATUS_UNSUCCESSFUL;
195         default:
196                 break;
197         }
198
199         if (ADS_ERR_OK(status)) {
200                 return NT_STATUS_OK;
201         }
202         return NT_STATUS_UNSUCCESSFUL;
203 }
204
205 /*
206   return a string for an error from an ads routine
207 */
208 const char *ads_errstr(ADS_STATUS status)
209 {
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));
217         default:
218                 return "Unknown ADS error type!? (not compiled in?)";
219         }
220 }
221
222 ADS_STATUS ads_build_ldap_error(int ldb_error)
223 {
224         ADS_STATUS ret;
225         ret.err.rc = ldb_error;
226         ret.error_type = ENUM_ADS_ERROR_LDAP;
227         return ret;
228 }
229
230 ADS_STATUS ads_build_nt_error(NTSTATUS nt_status)
231 {
232         ADS_STATUS ret;
233         ret.err.nt_status = nt_status;
234         ret.error_type = ENUM_ADS_ERROR_NT;
235         return ret;
236 }
237
238 /*
239   FIXME
240   Stub write functions, these do not do anything, though they should. -- Wilco
241 */
242
243 ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx)
244 {
245         return NULL;
246 }
247
248 ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, const char *val)
249 {
250         return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
251 }
252
253 ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods)
254 {
255         return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
256 }