Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : ads (active directory) printer utility library
4 : Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
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.h"
26 : #include "libcli/registry/util_reg.h"
27 :
28 : #ifdef HAVE_ADS
29 :
30 : /*
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.
34 : */
35 0 : ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
36 : const char *printer,
37 : const char *servername)
38 : {
39 0 : ADS_STATUS status;
40 0 : char *srv_dn, **srv_cn, *s = NULL;
41 0 : const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
42 :
43 0 : status = ads_find_machine_acct(ads, res, servername);
44 0 : if (!ADS_ERR_OK(status)) {
45 0 : DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
46 : servername));
47 0 : return status;
48 : }
49 0 : if (ads_count_replies(ads, *res) != 1) {
50 0 : ads_msgfree(ads, *res);
51 0 : *res = NULL;
52 0 : return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
53 : }
54 0 : srv_dn = ldap_get_dn(ads->ldap.ld, *res);
55 0 : if (srv_dn == NULL) {
56 0 : ads_msgfree(ads, *res);
57 0 : *res = NULL;
58 0 : return ADS_ERROR(LDAP_NO_MEMORY);
59 : }
60 0 : srv_cn = ldap_explode_dn(srv_dn, 1);
61 0 : if (srv_cn == NULL) {
62 0 : ldap_memfree(srv_dn);
63 0 : ads_msgfree(ads, *res);
64 0 : *res = NULL;
65 0 : return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
66 : }
67 0 : ads_msgfree(ads, *res);
68 0 : *res = NULL;
69 :
70 0 : if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
71 0 : ldap_memfree(srv_dn);
72 0 : return ADS_ERROR(LDAP_NO_MEMORY);
73 : }
74 0 : status = ads_search(ads, res, s, attrs);
75 :
76 0 : ldap_memfree(srv_dn);
77 0 : ldap_value_free(srv_cn);
78 0 : SAFE_FREE(s);
79 0 : return status;
80 : }
81 :
82 0 : ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
83 : {
84 0 : const char *ldap_expr;
85 0 : const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
86 : "serverName", "description", NULL };
87 :
88 : /* For the moment only display all printers */
89 :
90 0 : ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
91 : "(objectCategory=printQueue))";
92 :
93 0 : return ads_search(ads, res, ldap_expr, attrs);
94 : }
95 :
96 : /*
97 : modify a printer entry in the directory
98 : */
99 0 : ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
100 : TALLOC_CTX *ctx, const ADS_MODLIST *mods)
101 : {
102 0 : return ads_gen_mod(ads, prt_dn, *mods);
103 : }
104 :
105 : /*
106 : add a printer to the directory
107 : */
108 0 : ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
109 : TALLOC_CTX *ctx, ADS_MODLIST *mods)
110 : {
111 0 : ads_mod_str(ctx, mods, "objectClass", "printQueue");
112 0 : return ads_gen_add(ads, prt_dn, *mods);
113 : }
114 :
115 : /*
116 : map a REG_SZ to an ldap mod
117 : */
118 0 : static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
119 : const char *name, struct registry_value *value)
120 : {
121 0 : const char *str_value = NULL;
122 0 : ADS_STATUS status;
123 :
124 0 : if (value->type != REG_SZ)
125 0 : return false;
126 :
127 0 : if (value->data.length && value->data.data) {
128 0 : if (!pull_reg_sz(ctx, &value->data, &str_value)) {
129 0 : return false;
130 : }
131 0 : status = ads_mod_str(ctx, mods, name, str_value);
132 0 : return ADS_ERR_OK(status);
133 : }
134 0 : return true;
135 : }
136 :
137 : /*
138 : map a REG_DWORD to an ldap mod
139 : */
140 0 : static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
141 : const char *name, struct registry_value *value)
142 : {
143 0 : char *str_value = NULL;
144 0 : ADS_STATUS status;
145 :
146 0 : if (value->type != REG_DWORD) {
147 0 : return false;
148 : }
149 0 : if (value->data.length != sizeof(uint32_t)) {
150 0 : return false;
151 : }
152 0 : str_value = talloc_asprintf(ctx, "%d", IVAL(value->data.data, 0));
153 0 : if (!str_value) {
154 0 : return false;
155 : }
156 0 : status = ads_mod_str(ctx, mods, name, str_value);
157 0 : return ADS_ERR_OK(status);
158 : }
159 :
160 : /*
161 : map a boolean REG_BINARY to an ldap mod
162 : */
163 0 : static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
164 : const char *name, struct registry_value *value)
165 : {
166 0 : const char *str_value;
167 0 : ADS_STATUS status;
168 :
169 0 : if (value->type != REG_BINARY) {
170 0 : return false;
171 : }
172 0 : if (value->data.length != 1) {
173 0 : return false;
174 : }
175 :
176 0 : str_value = *value->data.data ? "TRUE" : "FALSE";
177 :
178 0 : status = ads_mod_str(ctx, mods, name, str_value);
179 0 : return ADS_ERR_OK(status);
180 : }
181 :
182 : /*
183 : map a REG_MULTI_SZ to an ldap mod
184 : */
185 0 : static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
186 : const char *name, struct registry_value *value)
187 : {
188 0 : const char **str_values = NULL;
189 0 : ADS_STATUS status;
190 :
191 0 : if (value->type != REG_MULTI_SZ) {
192 0 : return false;
193 : }
194 :
195 0 : if (value->data.length && value->data.data) {
196 0 : if (!pull_reg_multi_sz(ctx, &value->data, &str_values)) {
197 0 : return false;
198 : }
199 0 : status = ads_mod_strlist(ctx, mods, name, str_values);
200 0 : return ADS_ERR_OK(status);
201 : }
202 0 : return true;
203 : }
204 :
205 : struct valmap_to_ads {
206 : const char *valname;
207 : bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const char *, struct registry_value *);
208 : };
209 :
210 : /*
211 : map a REG_SZ to an ldap mod
212 : */
213 0 : static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
214 : const char *name, struct registry_value *value)
215 : {
216 0 : const struct valmap_to_ads map[] = {
217 : {SPOOL_REG_ASSETNUMBER, map_sz},
218 : {SPOOL_REG_BYTESPERMINUTE, map_dword},
219 : {SPOOL_REG_DEFAULTPRIORITY, map_dword},
220 : {SPOOL_REG_DESCRIPTION, map_sz},
221 : {SPOOL_REG_DRIVERNAME, map_sz},
222 : {SPOOL_REG_DRIVERVERSION, map_dword},
223 : {SPOOL_REG_FLAGS, map_dword},
224 : {SPOOL_REG_LOCATION, map_sz},
225 : {SPOOL_REG_OPERATINGSYSTEM, map_sz},
226 : {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
227 : {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
228 : {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
229 : {SPOOL_REG_PORTNAME, map_multi_sz},
230 : {SPOOL_REG_PRINTATTRIBUTES, map_dword},
231 : {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
232 : {SPOOL_REG_PRINTCOLLATE, map_bool},
233 : {SPOOL_REG_PRINTCOLOR, map_bool},
234 : {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
235 : {SPOOL_REG_PRINTENDTIME, map_dword},
236 : {SPOOL_REG_PRINTFORMNAME, map_sz},
237 : {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
238 : {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
239 : {SPOOL_REG_PRINTMACADDRESS, map_sz},
240 : {SPOOL_REG_PRINTMAXCOPIES, map_sz},
241 : {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
242 : {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
243 : {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
244 : {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
245 : {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
246 : {SPOOL_REG_PRINTMEMORY, map_dword},
247 : {SPOOL_REG_PRINTMINXEXTENT, map_dword},
248 : {SPOOL_REG_PRINTMINYEXTENT, map_dword},
249 : {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
250 : {SPOOL_REG_PRINTNOTIFY, map_sz},
251 : {SPOOL_REG_PRINTNUMBERUP, map_dword},
252 : {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
253 : {SPOOL_REG_PRINTOWNER, map_sz},
254 : {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
255 : {SPOOL_REG_PRINTRATE, map_dword},
256 : {SPOOL_REG_PRINTRATEUNIT, map_sz},
257 : {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
258 : {SPOOL_REG_PRINTSHARENAME, map_sz},
259 : {SPOOL_REG_PRINTSPOOLING, map_sz},
260 : {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
261 : {SPOOL_REG_PRINTSTARTTIME, map_dword},
262 : {SPOOL_REG_PRINTSTATUS, map_sz},
263 : {SPOOL_REG_PRIORITY, map_dword},
264 : {SPOOL_REG_SERVERNAME, map_sz},
265 : {SPOOL_REG_SHORTSERVERNAME, map_sz},
266 : {SPOOL_REG_UNCNAME, map_sz},
267 : {SPOOL_REG_URL, map_sz},
268 : {SPOOL_REG_VERSIONNUMBER, map_dword},
269 : {NULL, NULL}
270 : };
271 0 : int i;
272 :
273 0 : for (i=0; map[i].valname; i++) {
274 0 : if (strcasecmp_m(map[i].valname, name) == 0) {
275 0 : if (!map[i].fn(ctx, mods, name, value)) {
276 0 : DEBUG(5, ("Add of value %s to modlist failed\n", name));
277 : } else {
278 0 : DEBUG(7, ("Mapped value %s\n", name));
279 : }
280 : }
281 : }
282 0 : }
283 :
284 :
285 0 : WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
286 : TALLOC_CTX *mem_ctx,
287 : ADS_MODLIST *mods,
288 : const char *printer)
289 : {
290 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
291 0 : WERROR result;
292 0 : char *printername;
293 0 : struct spoolss_PrinterEnumValues *info;
294 0 : uint32_t count;
295 0 : uint32_t i;
296 0 : struct policy_handle pol;
297 0 : WERROR werr;
298 :
299 0 : if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
300 0 : DEBUG(3, ("Insufficient memory\n"));
301 0 : return WERR_NOT_ENOUGH_MEMORY;
302 : }
303 :
304 0 : result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
305 : printername,
306 : SEC_FLAG_MAXIMUM_ALLOWED,
307 : &pol);
308 0 : if (!W_ERROR_IS_OK(result)) {
309 0 : DEBUG(3, ("Unable to open printer %s, error is %s.\n",
310 : printername, win_errstr(result)));
311 0 : SAFE_FREE(printername);
312 0 : return result;
313 : }
314 :
315 0 : result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
316 : SPOOL_DSDRIVER_KEY,
317 : 0,
318 : &count,
319 : &info);
320 :
321 0 : if (!W_ERROR_IS_OK(result)) {
322 0 : DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
323 : printername, win_errstr(result)));
324 : } else {
325 : /* Have the data we need now, so start building */
326 0 : for (i=0; i < count; i++) {
327 0 : struct registry_value v;
328 0 : v.type = info[i].type;
329 0 : v.data = *info[i].data;
330 :
331 0 : map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
332 : }
333 : }
334 :
335 0 : result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
336 : SPOOL_DSSPOOLER_KEY,
337 : 0,
338 : &count,
339 : &info);
340 0 : if (!W_ERROR_IS_OK(result)) {
341 0 : DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
342 : printername, win_errstr(result)));
343 : } else {
344 0 : for (i=0; i < count; i++) {
345 0 : struct registry_value v;
346 0 : v.type = info[i].type;
347 0 : v.data = *info[i].data;
348 :
349 0 : map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
350 : }
351 : }
352 :
353 0 : ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
354 :
355 0 : dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr);
356 0 : SAFE_FREE(printername);
357 :
358 0 : return result;
359 : }
360 :
361 : #endif
|