1c64197b3d7e9d1fde4d8d5583f073854085877f
[kai/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/source/ads_convenience.h"
29
30 WERROR ads_startup (struct libnet_context *netctx, ADS_STRUCT **ads)
31 {
32         *ads = talloc(netctx, ADS_STRUCT);
33         *ads->netctx = netctx;
34
35         ads_connect(*ads);
36
37         return WERR_OK;
38 }
39
40 ADS_STATUS ads_connect(ADS_STRUCT *ads)
41 {
42         struct libnet_lookup_DCs *io;
43         char *url;
44
45         io = talloc_zero(ads, struct libnet_lookup_DCs);
46
47         /* We are looking for the PDC of the active domain. */
48         io->in.name_type = NBT_NAME_PDC;
49         io->in.domain_name = lp_workgroup(ads->netctx->lp_ctx);
50         libnet_lookupDCs(ads->netctx, ads, io);
51
52         url = talloc_asprintf(ads, "ldap://%s", io->out.dcs[0]);
53         ads->ldbctx = ldb_wrap_connect(ads, ads->netctx->event_ctx, ads->netctx->lp_ctx,
54                          url, NULL, ads->netctx->cred, 0, NULL);
55         if (ads->ldbctx == NULL) {
56                 return ADS_STATUS_NT(NT_STATUS_UNSUCCESSFUL);
57         }
58
59         return ADS_STATUS_NT(NT_STATUS_OK);
60 }
61
62 ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
63                          const char *dn, const char **attrs)
64 {
65         ADS_STATUS status;
66
67         status.err_state = ldb_search(ads->ldbctx, ads, res,
68                                       ldb_dn_new(ads, ads->ldbctx, dn),
69                                       LDB_SCOPE_BASE,
70                                       attrs,
71                                       "(objectclass=*)");
72
73         status.error_type = ENUM_ADS_ERROR_LDAP;
74         return status;
75 }
76
77 const char * ads_get_dn(ADS_STRUCT *ads, LDAPMessage *res)
78 {
79         return ldb_dn_get_linearized(res->msgs[0]->dn);
80 }
81
82 bool ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *ctx, LDAPMessage *res, const char *field, struct security_descriptor **sd)
83 {
84         struct ldb_val *val;
85         struct ndr_err_code ndr_err;
86
87         val = ldb_msg_find_ldb_val(res->msgs[0], field);
88
89         *sd = talloc(ctx, struct security_descriptor);
90         if (*sd == NULL) {
91                 return -1;
92         }
93         /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
94         ndr_err = ndr_pull_struct_blob(val, *sd, NULL, *sd,
95                                            (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
96         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
97                 talloc_free(*sd);
98                 return -1;
99         }
100         return 0;
101 }
102
103 ADS_STATUS ads_search_retry_dn_sd_flags(ADS_STRUCT *ads, LDAPMessage **res, uint32_t sd_flags,
104                                         const char *dn, const char **attrs)
105 {
106         return ads_search_sd_flags(ads, dn, LDB_SCOPE_BASE, "(objectclass=*)", attrs, sd_flags, res);
107 }
108
109 static ADS_STATUS ads_do_search_all_sd_flags (ADS_STRUCT *ads, const char *dn, int scope,
110                                               const char *filter, const char **attrs,
111                                               uint32_t sd_flags, LDAPMessage **res)
112 {
113         int count = 3;
114         int rv;
115         struct ldb_request *req;
116         struct ldb_control **controls;
117         struct ldb_parse_tree *tree;
118
119         controls = talloc_zero_array(ads, struct ldb_control *, 2);
120         controls[0] = talloc(ads, struct ldb_control);
121         controls[0]->oid = LDB_CONTROL_SD_FLAGS_OID;
122         controls[0]->data = &sd_flags;
123         controls[0]->critical = 1;
124
125         tree = ldb_parse_tree(ads, filter);
126
127         rv = ldb_build_search_req_ex(&req, ads->ldbctx, ads, res, dn, scope, tree, attrs, controls,
128                                      res, ldb_search_default_callback, NULL);
129         if (rv != LDB_SUCCESS) {
130                 talloc_free(*res);
131                 talloc_free(req);
132                 talloc_free(tree);
133                 return ADS_STATUS(irv);
134         }
135         rv = ldb_request(ads->ldbctx, req);
136         if (rv == LDB_SUCCESS) {
137                 rv = ldb_wait(req->handle, LDB_WAIT_ALL);
138         }
139
140         talloc_free(req);
141         talloc_free(tree);
142         return ADS_STATUS(rv);
143
144 }
145
146 const char * ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *ctx, LDAPMessage *res, const char *field)
147 {
148         return ldb_msg_find_attr_as_string(res->msgs[0], field, NULL);
149 }
150
151 bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *res, const char *field, uint32_t *ret)
152 {
153         if (ldb_msg_find_element(res->msgs[0], field) == NULL) {
154                 return false;
155         }
156         *ret = ldb_msg_find_attr_as_uint(res->msgs[0], field, 0);
157         return true;
158 }
159
160
161 int ads_count_replies(ADS_STRUCT *ads, LDAPMessage *res)
162 {
163         return res->count;
164 }
165
166 ADS_STATUS ads_msgfree(ADS_STRUCT *ads, LDAPMessage *res)
167 {
168         talloc_free(res);
169 }
170
171 /*
172   do a rough conversion between ads error codes and NT status codes
173   we'll need to fill this in more
174 */
175 NTSTATUS ads_ntstatus(ADS_STATUS status)
176 {
177         switch (status.error_type) {
178         case ENUM_ADS_ERROR_NT:
179                 return status.err.nt_status;
180         case ENUM_ADS_ERROR_SYSTEM:
181                 return map_nt_error_from_unix(status.err.rc);
182         case ENUM_ADS_ERROR_LDAP:
183                 if (status.err.rc == LDB_SUCCESS) {
184                         return NT_STATUS_OK;
185                 }
186                 return NT_STATUS_UNSUCCESSFUL;
187         default:
188                 break;
189         }
190
191         if (ADS_ERR_OK(status)) {
192                 return NT_STATUS_OK;
193         }
194         return NT_STATUS_UNSUCCESSFUL;
195 }
196
197 /*
198   return a string for an error from an ads routine
199 */
200 const char *ads_errstr(ADS_STATUS status)
201 {
202         switch (status.error_type) {
203         case ENUM_ADS_ERROR_SYSTEM:
204                 return strerror(status.err.rc);
205         case ENUM_ADS_ERROR_LDAP:
206                 return msg;
207         case ENUM_ADS_ERROR_NT:
208                 return get_friendly_nt_error_msg(ads_ntstatus(status));
209         default:
210                 return "Unknown ADS error type!? (not compiled in?)";
211         }
212 }
213
214 ADS_STATUS ads_build_ldap_error(int ldb_error)
215 {
216         ADS_STATUS ret;
217         ret.err.rc = ldb_error;
218         ret.error_type = ENUM_ADS_ERROR_LDAP;
219         return ret;
220 }
221
222 ADS_STATUS ads_build_nt_error(NTSTATUS nt_status)
223 {
224         ADS_STATUS ret;
225         ret.err.nt_status = nt_status;
226         ret.error_type = ENUM_ADS_ERROR_NT;
227         return ret;
228 }
229
230 /*
231   FIXME
232   Stub write functions, these do not do anything, though they should. -- Wilco
233 */
234
235 ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx)
236 {
237         return NULL;
238 }
239
240 ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, const char *val)
241 {
242         return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
243 }
244
245 ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods)
246 {
247         return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
248 }