s3: Fix Coverity ID 770, REVERSE_INULL
[Samba.git] / source3 / libads / ldap_printer.c
blob251dfb0a81548394f3b09be39a75d18251c6cd2d
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 "../librpc/gen_ndr/ndr_spoolss_c.h"
23 #include "rpc_client/cli_spoolss.h"
24 #include "registry.h"
25 #include "registry/reg_objects.h"
26 #include "nt_printing.h"
28 #ifdef HAVE_ADS
31 find a printer given the name and the hostname
32 Note that results "res" may be allocated on return so that the
33 results can be used. It should be freed using ads_msgfree.
35 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
36 const char *printer,
37 const char *servername)
39 ADS_STATUS status;
40 char *srv_dn, **srv_cn, *s = NULL;
41 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
43 status = ads_find_machine_acct(ads, res, servername);
44 if (!ADS_ERR_OK(status)) {
45 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
46 servername));
47 return status;
49 if (ads_count_replies(ads, *res) != 1) {
50 ads_msgfree(ads, *res);
51 *res = NULL;
52 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
54 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
55 if (srv_dn == NULL) {
56 ads_msgfree(ads, *res);
57 *res = NULL;
58 return ADS_ERROR(LDAP_NO_MEMORY);
60 srv_cn = ldap_explode_dn(srv_dn, 1);
61 if (srv_cn == NULL) {
62 ldap_memfree(srv_dn);
63 ads_msgfree(ads, *res);
64 *res = NULL;
65 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
67 ads_msgfree(ads, *res);
68 *res = NULL;
70 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
71 ldap_memfree(srv_dn);
72 return ADS_ERROR(LDAP_NO_MEMORY);
74 status = ads_search(ads, res, s, attrs);
76 ldap_memfree(srv_dn);
77 ldap_value_free(srv_cn);
78 SAFE_FREE(s);
79 return status;
82 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
84 const char *ldap_expr;
85 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
86 "serverName", "description", NULL };
88 /* For the moment only display all printers */
90 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
91 "(objectCategory=printQueue))";
93 return ads_search(ads, res, ldap_expr, attrs);
97 modify a printer entry in the directory
99 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
100 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
102 return ads_gen_mod(ads, prt_dn, *mods);
106 add a printer to the directory
108 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
109 TALLOC_CTX *ctx, ADS_MODLIST *mods)
111 ads_mod_str(ctx, mods, "objectClass", "printQueue");
112 return ads_gen_add(ads, prt_dn, *mods);
116 map a REG_SZ to an ldap mod
118 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
119 struct regval_blob *value)
121 char *str_value = NULL;
122 size_t converted_size;
123 ADS_STATUS status;
125 if (regval_type(value) != REG_SZ)
126 return false;
128 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
129 if (!pull_ucs2_talloc(ctx, &str_value,
130 (const smb_ucs2_t *) regval_data_p(value),
131 &converted_size))
133 return false;
135 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
136 return ADS_ERR_OK(status);
138 return true;
143 map a REG_DWORD to an ldap mod
145 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
146 struct regval_blob *value)
148 char *str_value = NULL;
149 ADS_STATUS status;
151 if (regval_type(value) != REG_DWORD)
152 return False;
153 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
154 if (!str_value) {
155 return False;
157 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
158 return ADS_ERR_OK(status);
162 map a boolean REG_BINARY to an ldap mod
164 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
165 struct regval_blob *value)
167 char *str_value;
168 ADS_STATUS status;
170 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
171 return False;
172 str_value = talloc_asprintf(ctx, "%s",
173 *(regval_data_p(value)) ? "TRUE" : "FALSE");
174 if (!str_value) {
175 return False;
177 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
178 return ADS_ERR_OK(status);
182 map a REG_MULTI_SZ to an ldap mod
184 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
185 struct regval_blob *value)
187 char **str_values = NULL;
188 size_t converted_size;
189 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
190 uint32 size = 0, num_vals = 0, i=0;
191 ADS_STATUS status;
193 if (regval_type(value) != REG_MULTI_SZ)
194 return False;
196 while(cur_str && *cur_str && (size < regval_size(value))) {
197 size += 2 * (strlen_w(cur_str) + 1);
198 cur_str += strlen_w(cur_str) + 1;
199 num_vals++;
202 if (num_vals) {
203 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
204 if (!str_values) {
205 return False;
207 memset(str_values, '\0',
208 (num_vals + 1) * sizeof(char *));
210 cur_str = (smb_ucs2_t *) regval_data_p(value);
211 for (i=0; i < num_vals; i++) {
212 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
213 cur_str, &converted_size) ?
214 converted_size : (size_t)-1;
217 status = ads_mod_strlist(ctx, mods, regval_name(value),
218 (const char **) str_values);
219 return ADS_ERR_OK(status);
221 return True;
224 struct valmap_to_ads {
225 const char *valname;
226 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
230 map a REG_SZ to an ldap mod
232 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
233 struct regval_blob *value)
235 const struct valmap_to_ads map[] = {
236 {SPOOL_REG_ASSETNUMBER, map_sz},
237 {SPOOL_REG_BYTESPERMINUTE, map_dword},
238 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
239 {SPOOL_REG_DESCRIPTION, map_sz},
240 {SPOOL_REG_DRIVERNAME, map_sz},
241 {SPOOL_REG_DRIVERVERSION, map_dword},
242 {SPOOL_REG_FLAGS, map_dword},
243 {SPOOL_REG_LOCATION, map_sz},
244 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
245 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
246 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
247 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
248 {SPOOL_REG_PORTNAME, map_multi_sz},
249 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
250 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
251 {SPOOL_REG_PRINTCOLLATE, map_bool},
252 {SPOOL_REG_PRINTCOLOR, map_bool},
253 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
254 {SPOOL_REG_PRINTENDTIME, map_dword},
255 {SPOOL_REG_PRINTFORMNAME, map_sz},
256 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
257 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
258 {SPOOL_REG_PRINTMACADDRESS, map_sz},
259 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
260 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
261 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
262 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
263 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
264 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
265 {SPOOL_REG_PRINTMEMORY, map_dword},
266 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
267 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
268 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
269 {SPOOL_REG_PRINTNOTIFY, map_sz},
270 {SPOOL_REG_PRINTNUMBERUP, map_dword},
271 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
272 {SPOOL_REG_PRINTOWNER, map_sz},
273 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
274 {SPOOL_REG_PRINTRATE, map_dword},
275 {SPOOL_REG_PRINTRATEUNIT, map_sz},
276 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
277 {SPOOL_REG_PRINTSHARENAME, map_sz},
278 {SPOOL_REG_PRINTSPOOLING, map_sz},
279 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
280 {SPOOL_REG_PRINTSTARTTIME, map_dword},
281 {SPOOL_REG_PRINTSTATUS, map_sz},
282 {SPOOL_REG_PRIORITY, map_dword},
283 {SPOOL_REG_SERVERNAME, map_sz},
284 {SPOOL_REG_SHORTSERVERNAME, map_sz},
285 {SPOOL_REG_UNCNAME, map_sz},
286 {SPOOL_REG_URL, map_sz},
287 {SPOOL_REG_VERSIONNUMBER, map_dword},
288 {NULL, NULL}
290 int i;
292 for (i=0; map[i].valname; i++) {
293 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
294 if (!map[i].fn(ctx, mods, value)) {
295 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
296 } else {
297 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
305 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
306 TALLOC_CTX *mem_ctx,
307 ADS_MODLIST *mods,
308 const char *printer)
310 struct dcerpc_binding_handle *b = cli->binding_handle;
311 WERROR result;
312 char *printername;
313 struct spoolss_PrinterEnumValues *info;
314 uint32_t count;
315 uint32 i;
316 struct policy_handle pol;
317 WERROR werr;
319 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
320 DEBUG(3, ("Insufficient memory\n"));
321 return WERR_NOMEM;
324 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
325 printername,
326 SEC_FLAG_MAXIMUM_ALLOWED,
327 &pol);
328 if (!W_ERROR_IS_OK(result)) {
329 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
330 printername, win_errstr(result)));
331 SAFE_FREE(printername);
332 return result;
335 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
336 SPOOL_DSDRIVER_KEY,
338 &count,
339 &info);
341 if (!W_ERROR_IS_OK(result)) {
342 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
343 printername, win_errstr(result)));
344 } else {
345 /* Have the data we need now, so start building */
346 for (i=0; i < count; i++) {
347 struct regval_blob *v;
349 v = regval_compose(mem_ctx, info[i].value_name,
350 info[i].type,
351 info[i].data->data,
352 info[i].data->length);
353 if (v == NULL) {
354 return WERR_NOMEM;
357 map_regval_to_ads(mem_ctx, mods, v);
358 talloc_free(v);
362 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
363 SPOOL_DSSPOOLER_KEY,
365 &count,
366 &info);
367 if (!W_ERROR_IS_OK(result)) {
368 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
369 printername, win_errstr(result)));
370 } else {
371 for (i=0; i < count; i++) {
372 struct regval_blob *v;
374 v = regval_compose(mem_ctx, info[i].value_name,
375 info[i].type,
376 info[i].data->data,
377 info[i].data->length);
378 if (v == NULL) {
379 return WERR_NOMEM;
382 map_regval_to_ads(mem_ctx, mods, v);
383 talloc_free(v);
387 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
389 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr);
390 SAFE_FREE(printername);
392 return result;
395 #endif