off by one bug in string length; CR 1159
[Samba.git] / source / libads / ldap_printer.c
blob87ea058896786e0ac150e0ea7c9cb441e2c174c8
1 /*
2 Unix SMB/CIFS implementation.
3 ads (active directory) printer utility library
4 Copyright (C) Jim McDonough 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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.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, void **res,
31 const char *printer, const char *servername)
33 ADS_STATUS status;
34 char *srv_dn, **srv_cn, *exp;
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_add_printer: cannot find host %s in ads\n",
40 servername));
41 return status;
43 srv_dn = ldap_get_dn(ads->ld, *res);
44 srv_cn = ldap_explode_dn(srv_dn, 1);
45 ads_msgfree(ads, *res);
47 asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer);
48 status = ads_search(ads, res, exp, attrs);
50 ldap_memfree(srv_dn);
51 ldap_value_free(srv_cn);
52 free(exp);
53 return status;
57 modify a printer entry in the directory
59 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
60 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
62 return ads_gen_mod(ads, prt_dn, *mods);
66 add a printer to the directory
68 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
69 TALLOC_CTX *ctx, ADS_MODLIST *mods)
71 ads_mod_str(ctx, mods, "objectClass", "printQueue");
72 return ads_gen_add(ads, prt_dn, *mods);
76 map a REG_SZ to an ldap mod
78 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
79 const REGISTRY_VALUE *value)
81 char *str_value = NULL;
82 ADS_STATUS status;
84 if (value->type != REG_SZ)
85 return False;
87 if (value->size && *((smb_ucs2_t *) value->data_p)) {
88 pull_ucs2_talloc(ctx, (void **) &str_value,
89 (const smb_ucs2_t *) value->data_p);
90 status = ads_mod_str(ctx, mods, value->valuename, str_value);
91 return ADS_ERR_OK(status);
93 return True;
98 map a REG_DWORD to an ldap mod
100 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
101 const REGISTRY_VALUE *value)
103 char *str_value = NULL;
104 ADS_STATUS status;
106 if (value->type != REG_DWORD)
107 return False;
108 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
109 status = ads_mod_str(ctx, mods, value->valuename, str_value);
110 return ADS_ERR_OK(status);
114 map a boolean REG_BINARY to an ldap mod
116 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
117 const REGISTRY_VALUE *value)
119 char *str_value;
120 ADS_STATUS status;
122 if ((value->type != REG_BINARY) || (value->size != 1))
123 return False;
124 str_value = talloc_asprintf(ctx, "%s",
125 *(value->data_p) ? "TRUE" : "FALSE");
126 status = ads_mod_str(ctx, mods, value->valuename, str_value);
127 return ADS_ERR_OK(status);
131 map a REG_MULTI_SZ to an ldap mod
133 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
134 const REGISTRY_VALUE *value)
136 char **str_values = NULL;
137 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
138 uint32 size = 0, num_vals = 0, i=0;
139 ADS_STATUS status;
141 if (value->type != REG_MULTI_SZ)
142 return False;
144 while(cur_str && *cur_str && (size < value->size)) {
145 size += 2 * (strlen_w(cur_str) + 1);
146 cur_str += strlen_w(cur_str) + 1;
147 num_vals++;
150 if (num_vals) {
151 str_values = talloc(ctx,
152 (num_vals + 1) * sizeof(smb_ucs2_t *));
153 memset(str_values, '\0',
154 (num_vals + 1) * sizeof(smb_ucs2_t *));
156 cur_str = (smb_ucs2_t *) value->data_p;
157 for (i=0; i < num_vals; i++)
158 cur_str += pull_ucs2_talloc(ctx,
159 (void **) &str_values[i],
160 cur_str);
162 status = ads_mod_strlist(ctx, mods, value->valuename,
163 (const char **) str_values);
164 return ADS_ERR_OK(status);
166 return True;
169 struct valmap_to_ads {
170 const char *valname;
171 BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
175 map a REG_SZ to an ldap mod
177 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
178 REGISTRY_VALUE *value)
180 const struct valmap_to_ads map[] = {
181 {SPOOL_REG_ASSETNUMBER, map_sz},
182 {SPOOL_REG_BYTESPERMINUTE, map_dword},
183 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
184 {SPOOL_REG_DESCRIPTION, map_sz},
185 {SPOOL_REG_DRIVERNAME, map_sz},
186 {SPOOL_REG_DRIVERVERSION, map_dword},
187 {SPOOL_REG_FLAGS, map_dword},
188 {SPOOL_REG_LOCATION, map_sz},
189 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
190 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
191 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
192 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
193 {SPOOL_REG_PORTNAME, map_multi_sz},
194 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
195 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
196 {SPOOL_REG_PRINTCOLLATE, map_bool},
197 {SPOOL_REG_PRINTCOLOR, map_bool},
198 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
199 {SPOOL_REG_PRINTENDTIME, map_dword},
200 {SPOOL_REG_PRINTFORMNAME, map_sz},
201 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
202 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
203 {SPOOL_REG_PRINTMACADDRESS, map_sz},
204 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
205 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
206 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
207 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
208 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
209 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
210 {SPOOL_REG_PRINTMEMORY, map_dword},
211 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
212 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
213 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
214 {SPOOL_REG_PRINTNOTIFY, map_sz},
215 {SPOOL_REG_PRINTNUMBERUP, map_dword},
216 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
217 {SPOOL_REG_PRINTOWNER, map_sz},
218 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
219 {SPOOL_REG_PRINTRATE, map_dword},
220 {SPOOL_REG_PRINTRATEUNIT, map_sz},
221 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
222 {SPOOL_REG_PRINTSHARENAME, map_sz},
223 {SPOOL_REG_PRINTSPOOLING, map_sz},
224 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
225 {SPOOL_REG_PRINTSTARTTIME, map_dword},
226 {SPOOL_REG_PRINTSTATUS, map_sz},
227 {SPOOL_REG_PRIORITY, map_dword},
228 {SPOOL_REG_SERVERNAME, map_sz},
229 {SPOOL_REG_SHORTSERVERNAME, map_sz},
230 {SPOOL_REG_UNCNAME, map_sz},
231 {SPOOL_REG_URL, map_sz},
232 {SPOOL_REG_VERSIONNUMBER, map_dword},
233 {NULL, NULL}
235 int i;
237 for (i=0; map[i].valname; i++) {
238 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
239 if (!map[i].fn(ctx, mods, value)) {
240 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
241 } else {
242 DEBUG(7, ("Mapped value %s\n", value->valuename));
250 WERROR get_remote_printer_publishing_data(struct cli_state *cli,
251 TALLOC_CTX *mem_ctx,
252 ADS_MODLIST *mods,
253 const char *printer)
255 WERROR result;
256 char *printername, *servername;
257 REGVAL_CTR dsdriver_ctr, dsspooler_ctr;
258 BOOL got_dsdriver = False, got_dsspooler = False;
259 uint32 needed, i;
260 POLICY_HND pol;
262 asprintf(&servername, "\\\\%s", cli->desthost);
263 asprintf(&printername, "%s\\%s", servername, printer);
264 if (!servername || !printername) {
265 DEBUG(3, ("Insufficient memory\n"));
266 return WERR_NOMEM;
269 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
270 "", MAXIMUM_ALLOWED_ACCESS,
271 servername, cli->user_name, &pol);
272 if (!W_ERROR_IS_OK(result)) {
273 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
274 printername, dos_errstr(result)));
275 return result;
278 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed,
279 &pol, SPOOL_DSDRIVER_KEY, NULL);
281 if (W_ERROR_V(result) == ERRmoredata)
282 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed,
283 NULL, &pol,
284 SPOOL_DSDRIVER_KEY,
285 &dsdriver_ctr);
287 if (!W_ERROR_IS_OK(result)) {
288 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
289 printername, dos_errstr(result)));
290 } else {
292 /* Have the data we need now, so start building */
293 got_dsdriver = True;
294 for (i=0; i < dsdriver_ctr.num_values; i++)
295 map_regval_to_ads(mem_ctx, mods,
296 dsdriver_ctr.values[i]);
299 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed,
300 &pol, SPOOL_DSSPOOLER_KEY,
301 NULL);
303 if (W_ERROR_V(result) == ERRmoredata)
304 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed,
305 NULL, &pol,
306 SPOOL_DSSPOOLER_KEY,
307 &dsspooler_ctr);
309 if (!W_ERROR_IS_OK(result)) {
310 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
311 printername, dos_errstr(result)));
312 } else {
313 got_dsspooler = True;
314 for (i=0; i < dsspooler_ctr.num_values; i++)
315 map_regval_to_ads(mem_ctx, mods,
316 dsspooler_ctr.values[i]);
319 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
321 if (got_dsdriver) regval_ctr_destroy(&dsdriver_ctr);
322 if (got_dsspooler) regval_ctr_destroy(&dsspooler_ctr);
323 cli_spoolss_close_printer(cli, mem_ctx, &pol);
325 return result;
328 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
329 ADS_MODLIST *mods,
330 NT_PRINTER_DATA *data)
332 uint32 key,val;
334 for (key=0; key < data->num_keys; key++) {
335 REGVAL_CTR ctr = data->keys[key].values;
336 for (val=0; val < ctr.num_values; val++)
337 map_regval_to_ads(mem_ctx, mods, ctr.values[val]);
339 return True;
342 #endif