CVE-2023-4154 dsdb/tests: Add test for SEARCH_FLAG_RODC_ATTRIBUTE behaviour
[Samba.git] / source3 / libads / ldap_printer.c
blobe610893ac4e469acf111aec9984bfbd9c8595c35
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.h"
26 #include "libcli/registry/util_reg.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 const char *name, struct registry_value *value)
121 const char *str_value = NULL;
122 ADS_STATUS status;
124 if (value->type != REG_SZ)
125 return false;
127 if (value->data.length && value->data.data) {
128 if (!pull_reg_sz(ctx, &value->data, &str_value)) {
129 return false;
131 status = ads_mod_str(ctx, mods, name, str_value);
132 return ADS_ERR_OK(status);
134 return true;
138 map a REG_DWORD to an ldap mod
140 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
141 const char *name, struct registry_value *value)
143 char *str_value = NULL;
144 ADS_STATUS status;
146 if (value->type != REG_DWORD) {
147 return false;
149 if (value->data.length != sizeof(uint32_t)) {
150 return false;
152 str_value = talloc_asprintf(ctx, "%d", IVAL(value->data.data, 0));
153 if (!str_value) {
154 return false;
156 status = ads_mod_str(ctx, mods, name, 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 const char *name, struct registry_value *value)
166 const char *str_value;
167 ADS_STATUS status;
169 if (value->type != REG_BINARY) {
170 return false;
172 if (value->data.length != 1) {
173 return false;
176 str_value = *value->data.data ? "TRUE" : "FALSE";
178 status = ads_mod_str(ctx, mods, name, str_value);
179 return ADS_ERR_OK(status);
183 map a REG_MULTI_SZ to an ldap mod
185 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
186 const char *name, struct registry_value *value)
188 const char **str_values = NULL;
189 ADS_STATUS status;
191 if (value->type != REG_MULTI_SZ) {
192 return false;
195 if (value->data.length && value->data.data) {
196 if (!pull_reg_multi_sz(ctx, &value->data, &str_values)) {
197 return false;
199 status = ads_mod_strlist(ctx, mods, name, str_values);
200 return ADS_ERR_OK(status);
202 return true;
205 struct valmap_to_ads {
206 const char *valname;
207 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const char *, struct registry_value *);
211 map a REG_SZ to an ldap mod
213 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
214 const char *name, struct registry_value *value)
216 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}
271 int i;
273 for (i=0; map[i].valname; i++) {
274 if (strcasecmp_m(map[i].valname, name) == 0) {
275 if (!map[i].fn(ctx, mods, name, value)) {
276 DEBUG(5, ("Add of value %s to modlist failed\n", name));
277 } else {
278 DEBUG(7, ("Mapped value %s\n", name));
285 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
286 TALLOC_CTX *mem_ctx,
287 ADS_MODLIST *mods,
288 const char *printer)
290 struct dcerpc_binding_handle *b = cli->binding_handle;
291 WERROR result;
292 char *printername;
293 struct spoolss_PrinterEnumValues *info;
294 uint32_t count;
295 uint32_t i;
296 struct policy_handle pol;
297 WERROR werr;
299 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
300 DEBUG(3, ("Insufficient memory\n"));
301 return WERR_NOT_ENOUGH_MEMORY;
304 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
305 printername,
306 SEC_FLAG_MAXIMUM_ALLOWED,
307 &pol);
308 if (!W_ERROR_IS_OK(result)) {
309 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
310 printername, win_errstr(result)));
311 SAFE_FREE(printername);
312 return result;
315 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
316 SPOOL_DSDRIVER_KEY,
318 &count,
319 &info);
321 if (!W_ERROR_IS_OK(result)) {
322 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 for (i=0; i < count; i++) {
327 struct registry_value v;
328 v.type = info[i].type;
329 v.data = *info[i].data;
331 map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
335 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
336 SPOOL_DSSPOOLER_KEY,
338 &count,
339 &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 for (i=0; i < count; i++) {
345 struct registry_value v;
346 v.type = info[i].type;
347 v.data = *info[i].data;
349 map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
353 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
355 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr);
356 SAFE_FREE(printername);
358 return result;
361 #endif