s3-spoolss: fix memleak in get_remote_printer_publishing_data().
[Samba.git] / source / libads / ldap_printer.c
blob3ff88466dd575363f2a18a05282cedf0f80c5bc9
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"
22 #ifdef HAVE_ADS
25 find a printer given the name and the hostname
26 Note that results "res" may be allocated on return so that the
27 results can be used. It should be freed using ads_msgfree.
29 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
30 const char *printer,
31 const char *servername)
33 ADS_STATUS status;
34 char *srv_dn, **srv_cn, *s = NULL;
35 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
37 status = ads_find_machine_acct(ads, res, servername);
38 if (!ADS_ERR_OK(status)) {
39 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
40 servername));
41 return status;
43 if (ads_count_replies(ads, *res) != 1) {
44 if (res) {
45 ads_msgfree(ads, *res);
46 *res = NULL;
48 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
50 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
51 if (srv_dn == NULL) {
52 if (res) {
53 ads_msgfree(ads, *res);
54 *res = NULL;
56 return ADS_ERROR(LDAP_NO_MEMORY);
58 srv_cn = ldap_explode_dn(srv_dn, 1);
59 if (srv_cn == NULL) {
60 ldap_memfree(srv_dn);
61 if (res) {
62 ads_msgfree(ads, *res);
63 *res = NULL;
65 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
67 if (res) {
68 ads_msgfree(ads, *res);
69 *res = NULL;
72 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
73 ldap_memfree(srv_dn);
74 return ADS_ERROR(LDAP_NO_MEMORY);
76 status = ads_search(ads, res, s, attrs);
78 ldap_memfree(srv_dn);
79 ldap_value_free(srv_cn);
80 SAFE_FREE(s);
81 return status;
84 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
86 const char *ldap_expr;
87 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
88 "serverName", "description", NULL };
90 /* For the moment only display all printers */
92 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
93 "(objectCategory=printQueue))";
95 return ads_search(ads, res, ldap_expr, attrs);
99 modify a printer entry in the directory
101 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
102 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
104 return ads_gen_mod(ads, prt_dn, *mods);
108 add a printer to the directory
110 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
111 TALLOC_CTX *ctx, ADS_MODLIST *mods)
113 ads_mod_str(ctx, mods, "objectClass", "printQueue");
114 return ads_gen_add(ads, prt_dn, *mods);
118 map a REG_SZ to an ldap mod
120 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
121 const REGISTRY_VALUE *value)
123 char *str_value = NULL;
124 size_t converted_size;
125 ADS_STATUS status;
127 if (value->type != REG_SZ)
128 return false;
130 if (value->size && *((smb_ucs2_t *) value->data_p)) {
131 if (!pull_ucs2_talloc(ctx, &str_value,
132 (const smb_ucs2_t *) value->data_p,
133 &converted_size))
135 return false;
137 status = ads_mod_str(ctx, mods, value->valuename, str_value);
138 return ADS_ERR_OK(status);
140 return true;
145 map a REG_DWORD to an ldap mod
147 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
148 const REGISTRY_VALUE *value)
150 char *str_value = NULL;
151 ADS_STATUS status;
153 if (value->type != REG_DWORD)
154 return False;
155 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
156 if (!str_value) {
157 return False;
159 status = ads_mod_str(ctx, mods, value->valuename, str_value);
160 return ADS_ERR_OK(status);
164 map a boolean REG_BINARY to an ldap mod
166 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
167 const REGISTRY_VALUE *value)
169 char *str_value;
170 ADS_STATUS status;
172 if ((value->type != REG_BINARY) || (value->size != 1))
173 return False;
174 str_value = talloc_asprintf(ctx, "%s",
175 *(value->data_p) ? "TRUE" : "FALSE");
176 if (!str_value) {
177 return False;
179 status = ads_mod_str(ctx, mods, value->valuename, str_value);
180 return ADS_ERR_OK(status);
184 map a REG_MULTI_SZ to an ldap mod
186 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
187 const REGISTRY_VALUE *value)
189 char **str_values = NULL;
190 size_t converted_size;
191 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
192 uint32 size = 0, num_vals = 0, i=0;
193 ADS_STATUS status;
195 if (value->type != REG_MULTI_SZ)
196 return False;
198 while(cur_str && *cur_str && (size < value->size)) {
199 size += 2 * (strlen_w(cur_str) + 1);
200 cur_str += strlen_w(cur_str) + 1;
201 num_vals++;
204 if (num_vals) {
205 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
206 if (!str_values) {
207 return False;
209 memset(str_values, '\0',
210 (num_vals + 1) * sizeof(char *));
212 cur_str = (smb_ucs2_t *) value->data_p;
213 for (i=0; i < num_vals; i++) {
214 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
215 cur_str, &converted_size) ?
216 converted_size : (size_t)-1;
219 status = ads_mod_strlist(ctx, mods, value->valuename,
220 (const char **) str_values);
221 return ADS_ERR_OK(status);
223 return True;
226 struct valmap_to_ads {
227 const char *valname;
228 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
232 map a REG_SZ to an ldap mod
234 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
235 REGISTRY_VALUE *value)
237 const struct valmap_to_ads map[] = {
238 {SPOOL_REG_ASSETNUMBER, map_sz},
239 {SPOOL_REG_BYTESPERMINUTE, map_dword},
240 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
241 {SPOOL_REG_DESCRIPTION, map_sz},
242 {SPOOL_REG_DRIVERNAME, map_sz},
243 {SPOOL_REG_DRIVERVERSION, map_dword},
244 {SPOOL_REG_FLAGS, map_dword},
245 {SPOOL_REG_LOCATION, map_sz},
246 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
247 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
248 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
249 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
250 {SPOOL_REG_PORTNAME, map_multi_sz},
251 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
252 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
253 {SPOOL_REG_PRINTCOLLATE, map_bool},
254 {SPOOL_REG_PRINTCOLOR, map_bool},
255 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
256 {SPOOL_REG_PRINTENDTIME, map_dword},
257 {SPOOL_REG_PRINTFORMNAME, map_sz},
258 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
259 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
260 {SPOOL_REG_PRINTMACADDRESS, map_sz},
261 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
262 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
263 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
264 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
265 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
266 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
267 {SPOOL_REG_PRINTMEMORY, map_dword},
268 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
269 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
270 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
271 {SPOOL_REG_PRINTNOTIFY, map_sz},
272 {SPOOL_REG_PRINTNUMBERUP, map_dword},
273 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
274 {SPOOL_REG_PRINTOWNER, map_sz},
275 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
276 {SPOOL_REG_PRINTRATE, map_dword},
277 {SPOOL_REG_PRINTRATEUNIT, map_sz},
278 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
279 {SPOOL_REG_PRINTSHARENAME, map_sz},
280 {SPOOL_REG_PRINTSPOOLING, map_sz},
281 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
282 {SPOOL_REG_PRINTSTARTTIME, map_dword},
283 {SPOOL_REG_PRINTSTATUS, map_sz},
284 {SPOOL_REG_PRIORITY, map_dword},
285 {SPOOL_REG_SERVERNAME, map_sz},
286 {SPOOL_REG_SHORTSERVERNAME, map_sz},
287 {SPOOL_REG_UNCNAME, map_sz},
288 {SPOOL_REG_URL, map_sz},
289 {SPOOL_REG_VERSIONNUMBER, map_dword},
290 {NULL, NULL}
292 int i;
294 for (i=0; map[i].valname; i++) {
295 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
296 if (!map[i].fn(ctx, mods, value)) {
297 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
298 } else {
299 DEBUG(7, ("Mapped value %s\n", value->valuename));
307 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
308 TALLOC_CTX *mem_ctx,
309 ADS_MODLIST *mods,
310 const char *printer)
312 WERROR result;
313 char *printername, *servername;
314 REGVAL_CTR *dsdriver_ctr, *dsspooler_ctr;
315 uint32 i;
316 POLICY_HND pol;
318 if ((asprintf(&servername, "\\\\%s", cli->desthost) == -1)
319 || (asprintf(&printername, "%s\\%s", servername, printer) == -1)) {
320 DEBUG(3, ("Insufficient memory\n"));
321 return WERR_NOMEM;
324 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
325 "", MAXIMUM_ALLOWED_ACCESS,
326 servername, cli->auth->user_name,
327 &pol);
328 if (!W_ERROR_IS_OK(result)) {
329 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
330 printername, dos_errstr(result)));
331 SAFE_FREE(printername);
332 return result;
335 if ( !(dsdriver_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) {
336 SAFE_FREE(printername);
337 return WERR_NOMEM;
340 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr);
342 if (!W_ERROR_IS_OK(result)) {
343 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
344 printername, dos_errstr(result)));
345 } else {
346 uint32 num_values = regval_ctr_numvals( dsdriver_ctr );
348 /* Have the data we need now, so start building */
349 for (i=0; i < num_values; i++) {
350 map_regval_to_ads(mem_ctx, mods, dsdriver_ctr->values[i]);
354 if ( !(dsspooler_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) {
355 SAFE_FREE(printername);
356 return WERR_NOMEM;
359 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr);
361 if (!W_ERROR_IS_OK(result)) {
362 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
363 printername, dos_errstr(result)));
364 } else {
365 uint32 num_values = regval_ctr_numvals( dsspooler_ctr );
367 for (i=0; i<num_values; i++) {
368 map_regval_to_ads(mem_ctx, mods, dsspooler_ctr->values[i]);
372 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
374 TALLOC_FREE( dsdriver_ctr );
375 TALLOC_FREE( dsspooler_ctr );
377 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
378 SAFE_FREE(printername);
380 return result;
383 bool get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
384 ADS_MODLIST *mods,
385 NT_PRINTER_DATA *data)
387 uint32 key,val;
389 for (key=0; key < data->num_keys; key++) {
390 REGVAL_CTR *ctr = data->keys[key].values;
391 for (val=0; val < ctr->num_values; val++)
392 map_regval_to_ads(mem_ctx, mods, ctr->values[val]);
394 return True;
397 #endif