Fix bug #10097 - MacOSX 10.9 will not follow path-based DFS referrals handed out...
[Samba.git] / source3 / libads / ldap_printer.c
blob664da8a60dcad9eca178aae8357f19b69fd2b849
1 /*
2 Unix SMB/CIFS implementation.
3 ads (active directory) printer utility library
4 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "ads.h"
22 #include "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "rpc_client/cli_spoolss.h"
25 #include "registry/reg_objects.h"
27 #ifdef HAVE_ADS
30 find a printer given the name and the hostname
31 Note that results "res" may be allocated on return so that the
32 results can be used. It should be freed using ads_msgfree.
34 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
35 const char *printer,
36 const char *servername)
38 ADS_STATUS status;
39 char *srv_dn, **srv_cn, *s = NULL;
40 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
42 status = ads_find_machine_acct(ads, res, servername);
43 if (!ADS_ERR_OK(status)) {
44 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
45 servername));
46 return status;
48 if (ads_count_replies(ads, *res) != 1) {
49 ads_msgfree(ads, *res);
50 *res = NULL;
51 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
53 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
54 if (srv_dn == NULL) {
55 ads_msgfree(ads, *res);
56 *res = NULL;
57 return ADS_ERROR(LDAP_NO_MEMORY);
59 srv_cn = ldap_explode_dn(srv_dn, 1);
60 if (srv_cn == NULL) {
61 ldap_memfree(srv_dn);
62 ads_msgfree(ads, *res);
63 *res = NULL;
64 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
66 ads_msgfree(ads, *res);
67 *res = NULL;
69 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
70 ldap_memfree(srv_dn);
71 return ADS_ERROR(LDAP_NO_MEMORY);
73 status = ads_search(ads, res, s, attrs);
75 ldap_memfree(srv_dn);
76 ldap_value_free(srv_cn);
77 SAFE_FREE(s);
78 return status;
81 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
83 const char *ldap_expr;
84 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
85 "serverName", "description", NULL };
87 /* For the moment only display all printers */
89 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
90 "(objectCategory=printQueue))";
92 return ads_search(ads, res, ldap_expr, attrs);
96 modify a printer entry in the directory
98 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
99 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
101 return ads_gen_mod(ads, prt_dn, *mods);
105 add a printer to the directory
107 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
108 TALLOC_CTX *ctx, ADS_MODLIST *mods)
110 ads_mod_str(ctx, mods, "objectClass", "printQueue");
111 return ads_gen_add(ads, prt_dn, *mods);
115 map a REG_SZ to an ldap mod
117 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
118 struct regval_blob *value)
120 char *str_value = NULL;
121 size_t converted_size;
122 ADS_STATUS status;
124 if (regval_type(value) != REG_SZ)
125 return false;
127 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
128 if (!pull_ucs2_talloc(ctx, &str_value,
129 (const smb_ucs2_t *) regval_data_p(value),
130 &converted_size))
132 return false;
134 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
135 return ADS_ERR_OK(status);
137 return true;
142 map a REG_DWORD to an ldap mod
144 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
145 struct regval_blob *value)
147 char *str_value = NULL;
148 ADS_STATUS status;
150 if (regval_type(value) != REG_DWORD)
151 return False;
152 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
153 if (!str_value) {
154 return False;
156 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
157 return ADS_ERR_OK(status);
161 map a boolean REG_BINARY to an ldap mod
163 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
164 struct regval_blob *value)
166 char *str_value;
167 ADS_STATUS status;
169 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
170 return False;
171 str_value = talloc_asprintf(ctx, "%s",
172 *(regval_data_p(value)) ? "TRUE" : "FALSE");
173 if (!str_value) {
174 return False;
176 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
177 return ADS_ERR_OK(status);
181 map a REG_MULTI_SZ to an ldap mod
183 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
184 struct regval_blob *value)
186 char **str_values = NULL;
187 size_t converted_size;
188 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
189 uint32 size = 0, num_vals = 0, i=0;
190 ADS_STATUS status;
192 if (regval_type(value) != REG_MULTI_SZ)
193 return False;
195 while(cur_str && *cur_str && (size < regval_size(value))) {
196 size += 2 * (strlen_w(cur_str) + 1);
197 cur_str += strlen_w(cur_str) + 1;
198 num_vals++;
201 if (num_vals) {
202 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
203 if (!str_values) {
204 return False;
206 memset(str_values, '\0',
207 (num_vals + 1) * sizeof(char *));
209 cur_str = (smb_ucs2_t *) regval_data_p(value);
210 for (i=0; i < num_vals; i++) {
211 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
212 cur_str, &converted_size) ?
213 converted_size : (size_t)-1;
216 status = ads_mod_strlist(ctx, mods, regval_name(value),
217 (const char **) str_values);
218 return ADS_ERR_OK(status);
220 return True;
223 struct valmap_to_ads {
224 const char *valname;
225 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
229 map a REG_SZ to an ldap mod
231 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
232 struct regval_blob *value)
234 const struct valmap_to_ads map[] = {
235 {SPOOL_REG_ASSETNUMBER, map_sz},
236 {SPOOL_REG_BYTESPERMINUTE, map_dword},
237 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
238 {SPOOL_REG_DESCRIPTION, map_sz},
239 {SPOOL_REG_DRIVERNAME, map_sz},
240 {SPOOL_REG_DRIVERVERSION, map_dword},
241 {SPOOL_REG_FLAGS, map_dword},
242 {SPOOL_REG_LOCATION, map_sz},
243 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
244 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
245 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
246 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
247 {SPOOL_REG_PORTNAME, map_multi_sz},
248 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
249 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
250 {SPOOL_REG_PRINTCOLLATE, map_bool},
251 {SPOOL_REG_PRINTCOLOR, map_bool},
252 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
253 {SPOOL_REG_PRINTENDTIME, map_dword},
254 {SPOOL_REG_PRINTFORMNAME, map_sz},
255 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
256 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
257 {SPOOL_REG_PRINTMACADDRESS, map_sz},
258 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
259 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
260 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
261 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
262 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
263 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
264 {SPOOL_REG_PRINTMEMORY, map_dword},
265 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
266 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
267 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
268 {SPOOL_REG_PRINTNOTIFY, map_sz},
269 {SPOOL_REG_PRINTNUMBERUP, map_dword},
270 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
271 {SPOOL_REG_PRINTOWNER, map_sz},
272 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
273 {SPOOL_REG_PRINTRATE, map_dword},
274 {SPOOL_REG_PRINTRATEUNIT, map_sz},
275 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
276 {SPOOL_REG_PRINTSHARENAME, map_sz},
277 {SPOOL_REG_PRINTSPOOLING, map_sz},
278 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
279 {SPOOL_REG_PRINTSTARTTIME, map_dword},
280 {SPOOL_REG_PRINTSTATUS, map_sz},
281 {SPOOL_REG_PRIORITY, map_dword},
282 {SPOOL_REG_SERVERNAME, map_sz},
283 {SPOOL_REG_SHORTSERVERNAME, map_sz},
284 {SPOOL_REG_UNCNAME, map_sz},
285 {SPOOL_REG_URL, map_sz},
286 {SPOOL_REG_VERSIONNUMBER, map_dword},
287 {NULL, NULL}
289 int i;
291 for (i=0; map[i].valname; i++) {
292 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
293 if (!map[i].fn(ctx, mods, value)) {
294 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
295 } else {
296 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
304 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
305 TALLOC_CTX *mem_ctx,
306 ADS_MODLIST *mods,
307 const char *printer)
309 struct dcerpc_binding_handle *b = cli->binding_handle;
310 WERROR result;
311 char *printername;
312 struct spoolss_PrinterEnumValues *info;
313 uint32_t count;
314 uint32 i;
315 struct policy_handle pol;
316 WERROR werr;
318 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
319 DEBUG(3, ("Insufficient memory\n"));
320 return WERR_NOMEM;
323 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
324 printername,
325 SEC_FLAG_MAXIMUM_ALLOWED,
326 &pol);
327 if (!W_ERROR_IS_OK(result)) {
328 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
329 printername, win_errstr(result)));
330 SAFE_FREE(printername);
331 return result;
334 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
335 SPOOL_DSDRIVER_KEY,
337 &count,
338 &info);
340 if (!W_ERROR_IS_OK(result)) {
341 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
342 printername, win_errstr(result)));
343 } else {
344 /* Have the data we need now, so start building */
345 for (i=0; i < count; i++) {
346 struct regval_blob *v;
348 v = regval_compose(mem_ctx, info[i].value_name,
349 info[i].type,
350 info[i].data->data,
351 info[i].data->length);
352 if (v == NULL) {
353 return WERR_NOMEM;
356 map_regval_to_ads(mem_ctx, mods, v);
357 talloc_free(v);
361 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
362 SPOOL_DSSPOOLER_KEY,
364 &count,
365 &info);
366 if (!W_ERROR_IS_OK(result)) {
367 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
368 printername, win_errstr(result)));
369 } else {
370 for (i=0; i < count; i++) {
371 struct regval_blob *v;
373 v = regval_compose(mem_ctx, info[i].value_name,
374 info[i].type,
375 info[i].data->data,
376 info[i].data->length);
377 if (v == NULL) {
378 return WERR_NOMEM;
381 map_regval_to_ads(mem_ctx, mods, v);
382 talloc_free(v);
386 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
388 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr);
389 SAFE_FREE(printername);
391 return result;
394 #endif