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