r6149: Fixes bugs #2498 and 2484.
[samba.git] / source3 / libads / ldap_printer.c
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #ifdef HAVE_ADS
24
25 /*
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.
29 */
30 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
31                                       const char *printer, const char *servername)
32 {
33         ADS_STATUS status;
34         char *srv_dn, **srv_cn, *s;
35         const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
36
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;
42         }
43         srv_dn = ldap_get_dn(ads->ld, *res);
44         srv_cn = ldap_explode_dn(srv_dn, 1);
45         ads_msgfree(ads, *res);
46
47         asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer);
48         status = ads_search(ads, res, s, attrs);
49
50         ldap_memfree(srv_dn);
51         ldap_value_free(srv_cn);
52         free(s);
53         return status;  
54 }
55
56 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res)
57 {
58         char *ldap_expr;
59         const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
60                                 "serverName", "description", NULL };
61
62         /* For the moment only display all printers */
63
64         ldap_expr =
65                 CONST_DISCARD(char *,
66                                 "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
67                                 "(objectCategory=printQueue))");
68
69         return ads_search(ads, res, ldap_expr, attrs);
70 }
71
72 /*
73   modify a printer entry in the directory
74 */
75 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
76                                  TALLOC_CTX *ctx, const ADS_MODLIST *mods)
77 {
78         return ads_gen_mod(ads, prt_dn, *mods);
79 }
80
81 /*
82   add a printer to the directory
83 */
84 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
85                                         TALLOC_CTX *ctx, ADS_MODLIST *mods)
86 {
87         ads_mod_str(ctx, mods, "objectClass", "printQueue");
88         return ads_gen_add(ads, prt_dn, *mods);
89 }
90
91 /*
92   map a REG_SZ to an ldap mod
93 */
94 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
95                             const REGISTRY_VALUE *value)
96 {
97         char *str_value = NULL;
98         ADS_STATUS status;
99
100         if (value->type != REG_SZ)
101                 return False;
102
103         if (value->size && *((smb_ucs2_t *) value->data_p)) {
104                 pull_ucs2_talloc(ctx, &str_value, (const smb_ucs2_t *) value->data_p);
105                 status = ads_mod_str(ctx, mods, value->valuename, str_value);
106                 return ADS_ERR_OK(status);
107         }
108         return True;
109                 
110 }
111
112 /*
113   map a REG_DWORD to an ldap mod
114 */
115 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
116                       const REGISTRY_VALUE *value)
117 {
118         char *str_value = NULL;
119         ADS_STATUS status;
120
121         if (value->type != REG_DWORD)
122                 return False;
123         str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
124         status = ads_mod_str(ctx, mods, value->valuename, str_value);
125         return ADS_ERR_OK(status);
126 }
127
128 /*
129   map a boolean REG_BINARY to an ldap mod
130 */
131 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
132                      const REGISTRY_VALUE *value)
133 {
134         char *str_value;
135         ADS_STATUS status;
136
137         if ((value->type != REG_BINARY) || (value->size != 1))
138                 return False;
139         str_value =  talloc_asprintf(ctx, "%s", 
140                                      *(value->data_p) ? "TRUE" : "FALSE");
141         status = ads_mod_str(ctx, mods, value->valuename, str_value);
142         return ADS_ERR_OK(status);
143 }
144
145 /*
146   map a REG_MULTI_SZ to an ldap mod
147 */
148 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
149                          const REGISTRY_VALUE *value)
150 {
151         char **str_values = NULL;
152         smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
153         uint32 size = 0, num_vals = 0, i=0;
154         ADS_STATUS status;
155
156         if (value->type != REG_MULTI_SZ)
157                 return False;
158
159         while(cur_str && *cur_str && (size < value->size)) {            
160                 size += 2 * (strlen_w(cur_str) + 1);
161                 cur_str += strlen_w(cur_str) + 1;
162                 num_vals++;
163         };
164
165         if (num_vals) {
166                 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
167                 memset(str_values, '\0', 
168                        (num_vals + 1) * sizeof(char *));
169
170                 cur_str = (smb_ucs2_t *) value->data_p;
171                 for (i=0; i < num_vals; i++)
172                         cur_str += pull_ucs2_talloc(ctx, &str_values[i],
173                                                     cur_str);
174
175                 status = ads_mod_strlist(ctx, mods, value->valuename, 
176                                          (const char **) str_values);
177                 return ADS_ERR_OK(status);
178         } 
179         return True;
180 }
181
182 struct valmap_to_ads {
183         const char *valname;
184         BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
185 };
186
187 /*
188   map a REG_SZ to an ldap mod
189 */
190 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
191                               REGISTRY_VALUE *value)
192 {
193         const struct valmap_to_ads map[] = {
194                 {SPOOL_REG_ASSETNUMBER, map_sz},
195                 {SPOOL_REG_BYTESPERMINUTE, map_dword},
196                 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
197                 {SPOOL_REG_DESCRIPTION, map_sz},
198                 {SPOOL_REG_DRIVERNAME, map_sz},
199                 {SPOOL_REG_DRIVERVERSION, map_dword},
200                 {SPOOL_REG_FLAGS, map_dword},
201                 {SPOOL_REG_LOCATION, map_sz},
202                 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
203                 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
204                 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
205                 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
206                 {SPOOL_REG_PORTNAME, map_multi_sz},
207                 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
208                 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
209                 {SPOOL_REG_PRINTCOLLATE, map_bool},
210                 {SPOOL_REG_PRINTCOLOR, map_bool},
211                 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
212                 {SPOOL_REG_PRINTENDTIME, map_dword},
213                 {SPOOL_REG_PRINTFORMNAME, map_sz},
214                 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
215                 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
216                 {SPOOL_REG_PRINTMACADDRESS, map_sz},
217                 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
218                 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
219                 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
220                 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
221                 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
222                 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
223                 {SPOOL_REG_PRINTMEMORY, map_dword},
224                 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
225                 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
226                 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
227                 {SPOOL_REG_PRINTNOTIFY, map_sz},
228                 {SPOOL_REG_PRINTNUMBERUP, map_dword},
229                 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
230                 {SPOOL_REG_PRINTOWNER, map_sz},
231                 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
232                 {SPOOL_REG_PRINTRATE, map_dword},
233                 {SPOOL_REG_PRINTRATEUNIT, map_sz},
234                 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
235                 {SPOOL_REG_PRINTSHARENAME, map_sz},
236                 {SPOOL_REG_PRINTSPOOLING, map_sz},
237                 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
238                 {SPOOL_REG_PRINTSTARTTIME, map_dword},
239                 {SPOOL_REG_PRINTSTATUS, map_sz},
240                 {SPOOL_REG_PRIORITY, map_dword},
241                 {SPOOL_REG_SERVERNAME, map_sz},
242                 {SPOOL_REG_SHORTSERVERNAME, map_sz},
243                 {SPOOL_REG_UNCNAME, map_sz},
244                 {SPOOL_REG_URL, map_sz},
245                 {SPOOL_REG_VERSIONNUMBER, map_dword},
246                 {NULL, NULL}
247         };
248         int i;
249
250         for (i=0; map[i].valname; i++) {
251                 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
252                         if (!map[i].fn(ctx, mods, value)) {
253                                 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
254                         } else {
255                                 DEBUG(7, ("Mapped value %s\n", value->valuename));
256                         }
257                         
258                 }
259         }
260 }
261
262
263 WERROR get_remote_printer_publishing_data(struct cli_state *cli, 
264                                           TALLOC_CTX *mem_ctx,
265                                           ADS_MODLIST *mods,
266                                           const char *printer)
267 {
268         WERROR result;
269         char *printername, *servername;
270         REGVAL_CTR dsdriver_ctr, dsspooler_ctr;
271         BOOL got_dsdriver = False, got_dsspooler = False;
272         uint32 needed, i;
273         POLICY_HND pol;
274
275         asprintf(&servername, "\\\\%s", cli->desthost);
276         asprintf(&printername, "%s\\%s", servername, printer);
277         if (!servername || !printername) {
278                 DEBUG(3, ("Insufficient memory\n"));
279                 return WERR_NOMEM;
280         }
281         
282         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
283                                              "", MAXIMUM_ALLOWED_ACCESS, 
284                                              servername, cli->user_name, &pol);
285         if (!W_ERROR_IS_OK(result)) {
286                 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
287                           printername, dos_errstr(result)));
288                 return result;
289         }
290         
291         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
292                                                &pol, SPOOL_DSDRIVER_KEY, NULL);
293
294         if (W_ERROR_V(result) == ERRmoredata)
295                 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
296                                                        NULL, &pol, 
297                                                        SPOOL_DSDRIVER_KEY,
298                                                        &dsdriver_ctr);
299
300         if (!W_ERROR_IS_OK(result)) {
301                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
302                           printername, dos_errstr(result)));
303         } else {
304
305                 /* Have the data we need now, so start building */
306                 got_dsdriver = True;
307                 for (i=0; i < dsdriver_ctr.num_values; i++)
308                         map_regval_to_ads(mem_ctx, mods, 
309                                           dsdriver_ctr.values[i]);
310         }
311         
312         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
313                                                &pol, SPOOL_DSSPOOLER_KEY, 
314                                                NULL);
315
316         if (W_ERROR_V(result) == ERRmoredata)
317                 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
318                                                        NULL, &pol, 
319                                                        SPOOL_DSSPOOLER_KEY,
320                                                        &dsspooler_ctr);
321
322         if (!W_ERROR_IS_OK(result)) {
323                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
324                           printername, dos_errstr(result)));
325         } else {
326                 got_dsspooler = True;
327                 for (i=0; i < dsspooler_ctr.num_values; i++)
328                         map_regval_to_ads(mem_ctx, mods, 
329                                           dsspooler_ctr.values[i]);
330         }
331         
332         ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
333
334         if (got_dsdriver) regval_ctr_destroy(&dsdriver_ctr);
335         if (got_dsspooler) regval_ctr_destroy(&dsspooler_ctr);
336         cli_spoolss_close_printer(cli, mem_ctx, &pol);
337
338         return result;
339 }
340
341 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
342                                        ADS_MODLIST *mods,
343                                        NT_PRINTER_DATA *data)
344 {
345         uint32 key,val;
346
347         for (key=0; key < data->num_keys; key++) {
348                 REGVAL_CTR ctr = data->keys[key].values;
349                 for (val=0; val < ctr.num_values; val++)
350                         map_regval_to_ads(mem_ctx, mods, ctr.values[val]);
351         }
352         return True;
353 }
354
355 #endif