s3:winbindd: Fix a brown paper bag bug in wbinfo -t ...
[Samba.git] / source3 / libads / ldap_printer.c
blobb5a3e6ba43de13e9ae84cb8661f5aea2b5b52706
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 "../librpc/gen_ndr/cli_spoolss.h"
23 #ifdef HAVE_ADS
26 find a printer given the name and the hostname
27 Note that results "res" may be allocated on return so that the
28 results can be used. It should be freed using ads_msgfree.
30 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
31 const char *printer,
32 const char *servername)
34 ADS_STATUS status;
35 char *srv_dn, **srv_cn, *s = NULL;
36 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
38 status = ads_find_machine_acct(ads, res, servername);
39 if (!ADS_ERR_OK(status)) {
40 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
41 servername));
42 return status;
44 if (ads_count_replies(ads, *res) != 1) {
45 if (res) {
46 ads_msgfree(ads, *res);
47 *res = NULL;
49 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
51 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
52 if (srv_dn == NULL) {
53 if (res) {
54 ads_msgfree(ads, *res);
55 *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 if (res) {
63 ads_msgfree(ads, *res);
64 *res = NULL;
66 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
68 if (res) {
69 ads_msgfree(ads, *res);
70 *res = NULL;
73 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
74 ldap_memfree(srv_dn);
75 return ADS_ERROR(LDAP_NO_MEMORY);
77 status = ads_search(ads, res, s, attrs);
79 ldap_memfree(srv_dn);
80 ldap_value_free(srv_cn);
81 SAFE_FREE(s);
82 return status;
85 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
87 const char *ldap_expr;
88 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
89 "serverName", "description", NULL };
91 /* For the moment only display all printers */
93 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
94 "(objectCategory=printQueue))";
96 return ads_search(ads, res, ldap_expr, attrs);
100 modify a printer entry in the directory
102 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
103 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
105 return ads_gen_mod(ads, prt_dn, *mods);
109 add a printer to the directory
111 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
112 TALLOC_CTX *ctx, ADS_MODLIST *mods)
114 ads_mod_str(ctx, mods, "objectClass", "printQueue");
115 return ads_gen_add(ads, prt_dn, *mods);
119 map a REG_SZ to an ldap mod
121 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
122 const struct regval_blob *value)
124 char *str_value = NULL;
125 size_t converted_size;
126 ADS_STATUS status;
128 if (value->type != REG_SZ)
129 return false;
131 if (value->size && *((smb_ucs2_t *) value->data_p)) {
132 if (!pull_ucs2_talloc(ctx, &str_value,
133 (const smb_ucs2_t *) value->data_p,
134 &converted_size))
136 return false;
138 status = ads_mod_str(ctx, mods, value->valuename, str_value);
139 return ADS_ERR_OK(status);
141 return true;
146 map a REG_DWORD to an ldap mod
148 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
149 const struct regval_blob *value)
151 char *str_value = NULL;
152 ADS_STATUS status;
154 if (value->type != REG_DWORD)
155 return False;
156 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
157 if (!str_value) {
158 return False;
160 status = ads_mod_str(ctx, mods, value->valuename, str_value);
161 return ADS_ERR_OK(status);
165 map a boolean REG_BINARY to an ldap mod
167 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
168 const struct regval_blob *value)
170 char *str_value;
171 ADS_STATUS status;
173 if ((value->type != REG_BINARY) || (value->size != 1))
174 return False;
175 str_value = talloc_asprintf(ctx, "%s",
176 *(value->data_p) ? "TRUE" : "FALSE");
177 if (!str_value) {
178 return False;
180 status = ads_mod_str(ctx, mods, value->valuename, str_value);
181 return ADS_ERR_OK(status);
185 map a REG_MULTI_SZ to an ldap mod
187 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
188 const struct regval_blob *value)
190 char **str_values = NULL;
191 size_t converted_size;
192 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
193 uint32 size = 0, num_vals = 0, i=0;
194 ADS_STATUS status;
196 if (value->type != REG_MULTI_SZ)
197 return False;
199 while(cur_str && *cur_str && (size < value->size)) {
200 size += 2 * (strlen_w(cur_str) + 1);
201 cur_str += strlen_w(cur_str) + 1;
202 num_vals++;
205 if (num_vals) {
206 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
207 if (!str_values) {
208 return False;
210 memset(str_values, '\0',
211 (num_vals + 1) * sizeof(char *));
213 cur_str = (smb_ucs2_t *) value->data_p;
214 for (i=0; i < num_vals; i++) {
215 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
216 cur_str, &converted_size) ?
217 converted_size : (size_t)-1;
220 status = ads_mod_strlist(ctx, mods, value->valuename,
221 (const char **) str_values);
222 return ADS_ERR_OK(status);
224 return True;
227 struct valmap_to_ads {
228 const char *valname;
229 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const struct regval_blob *);
233 map a REG_SZ to an ldap mod
235 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
236 struct regval_blob *value)
238 const struct valmap_to_ads map[] = {
239 {SPOOL_REG_ASSETNUMBER, map_sz},
240 {SPOOL_REG_BYTESPERMINUTE, map_dword},
241 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
242 {SPOOL_REG_DESCRIPTION, map_sz},
243 {SPOOL_REG_DRIVERNAME, map_sz},
244 {SPOOL_REG_DRIVERVERSION, map_dword},
245 {SPOOL_REG_FLAGS, map_dword},
246 {SPOOL_REG_LOCATION, map_sz},
247 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
248 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
249 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
250 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
251 {SPOOL_REG_PORTNAME, map_multi_sz},
252 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
253 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
254 {SPOOL_REG_PRINTCOLLATE, map_bool},
255 {SPOOL_REG_PRINTCOLOR, map_bool},
256 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
257 {SPOOL_REG_PRINTENDTIME, map_dword},
258 {SPOOL_REG_PRINTFORMNAME, map_sz},
259 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
260 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
261 {SPOOL_REG_PRINTMACADDRESS, map_sz},
262 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
263 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
264 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
265 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
266 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
267 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
268 {SPOOL_REG_PRINTMEMORY, map_dword},
269 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
270 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
271 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
272 {SPOOL_REG_PRINTNOTIFY, map_sz},
273 {SPOOL_REG_PRINTNUMBERUP, map_dword},
274 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
275 {SPOOL_REG_PRINTOWNER, map_sz},
276 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
277 {SPOOL_REG_PRINTRATE, map_dword},
278 {SPOOL_REG_PRINTRATEUNIT, map_sz},
279 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
280 {SPOOL_REG_PRINTSHARENAME, map_sz},
281 {SPOOL_REG_PRINTSPOOLING, map_sz},
282 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
283 {SPOOL_REG_PRINTSTARTTIME, map_dword},
284 {SPOOL_REG_PRINTSTATUS, map_sz},
285 {SPOOL_REG_PRIORITY, map_dword},
286 {SPOOL_REG_SERVERNAME, map_sz},
287 {SPOOL_REG_SHORTSERVERNAME, map_sz},
288 {SPOOL_REG_UNCNAME, map_sz},
289 {SPOOL_REG_URL, map_sz},
290 {SPOOL_REG_VERSIONNUMBER, map_dword},
291 {NULL, NULL}
293 int i;
295 for (i=0; map[i].valname; i++) {
296 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
297 if (!map[i].fn(ctx, mods, value)) {
298 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
299 } else {
300 DEBUG(7, ("Mapped value %s\n", value->valuename));
308 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
309 TALLOC_CTX *mem_ctx,
310 ADS_MODLIST *mods,
311 const char *printer)
313 WERROR result;
314 char *printername;
315 struct spoolss_PrinterEnumValues *info;
316 uint32_t count;
317 uint32 i;
318 struct policy_handle pol;
320 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
321 DEBUG(3, ("Insufficient memory\n"));
322 return WERR_NOMEM;
325 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
326 printername,
327 SEC_FLAG_MAXIMUM_ALLOWED,
328 &pol);
329 if (!W_ERROR_IS_OK(result)) {
330 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
331 printername, win_errstr(result)));
332 SAFE_FREE(printername);
333 return result;
336 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
337 SPOOL_DSDRIVER_KEY,
339 &count,
340 &info);
342 if (!W_ERROR_IS_OK(result)) {
343 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
344 printername, win_errstr(result)));
345 } else {
346 /* Have the data we need now, so start building */
347 for (i=0; i < count; i++) {
348 struct regval_blob v;
349 DATA_BLOB blob;
351 result = push_spoolss_PrinterData(mem_ctx, &blob,
352 info[i].type,
353 info[i].data);
354 if (W_ERROR_IS_OK(result)) {
355 fstrcpy(v.valuename, info[i].value_name);
356 v.type = info[i].type;
357 v.data_p = blob.data;
358 v.size = blob.length;
360 map_regval_to_ads(mem_ctx, mods, &v);
365 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
366 SPOOL_DSSPOOLER_KEY,
368 &count,
369 &info);
370 if (!W_ERROR_IS_OK(result)) {
371 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
372 printername, win_errstr(result)));
373 } else {
374 for (i=0; i < count; i++) {
375 struct regval_blob v;
376 DATA_BLOB blob = data_blob_null;
378 result = push_spoolss_PrinterData(mem_ctx, &blob,
379 info[i].type,
380 info[i].data);
381 if (W_ERROR_IS_OK(result)) {
382 fstrcpy(v.valuename, info[i].value_name);
383 v.type = info[i].type;
384 v.data_p = blob.data;
385 v.size = blob.length;
387 map_regval_to_ads(mem_ctx, mods, &v);
392 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
394 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
395 SAFE_FREE(printername);
397 return result;
400 bool get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
401 ADS_MODLIST *mods,
402 NT_PRINTER_DATA *data)
404 uint32 key,val;
406 for (key=0; key < data->num_keys; key++) {
407 struct regval_ctr *ctr = data->keys[key].values;
408 for (val=0; val < ctr->num_values; val++)
409 map_regval_to_ads(mem_ctx, mods, ctr->values[val]);
411 return True;
414 #endif