r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the
[ab/samba.git/.git] / source4 / 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_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 && SVAL(value->data_p, 0)) {
102                 pull_ucs2_talloc(ctx, &str_value, 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_t *) 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         char *cur_str = value->data_p;
151         uint32_t 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_t this_size = utf16_len(cur_str);
159                 cur_str += this_size;
160                 size += this_size;
161                 num_vals++;
162         };
163
164         if (num_vals) {
165                 str_values = talloc_array(ctx, char *, num_vals + 1);
166                 cur_str = value->data_p;
167                 for (i=0; i < num_vals; i++) {
168                         pull_ucs2_talloc(ctx, &str_values[i], cur_str);
169                         cur_str += utf16_len(cur_str);
170                 }
171                 str_values[i] = NULL;
172
173                 status = ads_mod_strlist(ctx, mods, value->valuename, 
174                                          (const char **) str_values);
175                 return ADS_ERR_OK(status);
176         } 
177         return True;
178 }
179
180 struct valmap_to_ads {
181         const char *valname;
182         BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
183 };
184
185 /*
186   map a REG_SZ to an ldap mod
187 */
188 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
189                               REGISTRY_VALUE *value)
190 {
191         const struct valmap_to_ads map[] = {
192                 {SPOOL_REG_ASSETNUMBER, map_sz},
193                 {SPOOL_REG_BYTESPERMINUTE, map_dword},
194                 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
195                 {SPOOL_REG_DESCRIPTION, map_sz},
196                 {SPOOL_REG_DRIVERNAME, map_sz},
197                 {SPOOL_REG_DRIVERVERSION, map_dword},
198                 {SPOOL_REG_FLAGS, map_dword},
199                 {SPOOL_REG_LOCATION, map_sz},
200                 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
201                 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
202                 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
203                 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
204                 {SPOOL_REG_PORTNAME, map_multi_sz},
205                 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
206                 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
207                 {SPOOL_REG_PRINTCOLLATE, map_bool},
208                 {SPOOL_REG_PRINTCOLOR, map_bool},
209                 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
210                 {SPOOL_REG_PRINTENDTIME, map_dword},
211                 {SPOOL_REG_PRINTFORMNAME, map_sz},
212                 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
213                 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
214                 {SPOOL_REG_PRINTMACADDRESS, map_sz},
215                 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
216                 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
217                 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
218                 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
219                 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
220                 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
221                 {SPOOL_REG_PRINTMEMORY, map_dword},
222                 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
223                 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
224                 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
225                 {SPOOL_REG_PRINTNOTIFY, map_sz},
226                 {SPOOL_REG_PRINTNUMBERUP, map_dword},
227                 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
228                 {SPOOL_REG_PRINTOWNER, map_sz},
229                 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
230                 {SPOOL_REG_PRINTRATE, map_dword},
231                 {SPOOL_REG_PRINTRATEUNIT, map_sz},
232                 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
233                 {SPOOL_REG_PRINTSHARENAME, map_sz},
234                 {SPOOL_REG_PRINTSPOOLING, map_sz},
235                 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
236                 {SPOOL_REG_PRINTSTARTTIME, map_dword},
237                 {SPOOL_REG_PRINTSTATUS, map_sz},
238                 {SPOOL_REG_PRIORITY, map_dword},
239                 {SPOOL_REG_SERVERNAME, map_sz},
240                 {SPOOL_REG_SHORTSERVERNAME, map_sz},
241                 {SPOOL_REG_UNCNAME, map_sz},
242                 {SPOOL_REG_URL, map_sz},
243                 {SPOOL_REG_VERSIONNUMBER, map_dword},
244                 {NULL, NULL}
245         };
246         int i;
247
248         for (i=0; map[i].valname; i++) {
249                 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
250                         if (!map[i].fn(ctx, mods, value)) {
251                                 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
252                         } else {
253                                 DEBUG(7, ("Mapped value %s\n", value->valuename));
254                         }
255                         
256                 }
257         }
258 }
259
260
261 WERROR get_remote_printer_publishing_data(struct smbcli_state *cli, 
262                                           TALLOC_CTX *mem_ctx,
263                                           ADS_MODLIST *mods,
264                                           const char *printer)
265 {
266         WERROR result;
267         char *printername, *servername;
268         REGVAL_CTR dsdriver_ctr, dsspooler_ctr;
269         BOOL got_dsdriver = False, got_dsspooler = False;
270         uint32_t needed, i;
271         POLICY_HND pol;
272
273         asprintf(&servername, "\\\\%s", cli->desthost);
274         asprintf(&printername, "%s\\%s", servername, printer);
275         if (!servername || !printername) {
276                 DEBUG(3, ("Insufficient memory\n"));
277                 return WERR_NOMEM;
278         }
279         
280         result = smbcli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
281                                              "", MAXIMUM_ALLOWED_ACCESS, 
282                                              servername, cli->user_name, &pol);
283         if (!W_ERROR_IS_OK(result)) {
284                 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
285                           printername, dos_errstr(result)));
286                 return result;
287         }
288         
289         result = smbcli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
290                                                &pol, SPOOL_DSDRIVER_KEY, NULL);
291
292         if (W_ERROR_V(result) == ERRmoredata)
293                 result = smbcli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
294                                                        NULL, &pol, 
295                                                        SPOOL_DSDRIVER_KEY,
296                                                        &dsdriver_ctr);
297
298         if (!W_ERROR_IS_OK(result)) {
299                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
300                           printername, dos_errstr(result)));
301         } else {
302
303                 /* Have the data we need now, so start building */
304                 got_dsdriver = True;
305                 for (i=0; i < dsdriver_ctr.num_values; i++)
306                         map_regval_to_ads(mem_ctx, mods, 
307                                           dsdriver_ctr.values[i]);
308         }
309         
310         result = smbcli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
311                                                &pol, SPOOL_DSSPOOLER_KEY, 
312                                                NULL);
313
314         if (W_ERROR_V(result) == ERRmoredata)
315                 result = smbcli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
316                                                        NULL, &pol, 
317                                                        SPOOL_DSSPOOLER_KEY,
318                                                        &dsspooler_ctr);
319
320         if (!W_ERROR_IS_OK(result)) {
321                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
322                           printername, dos_errstr(result)));
323         } else {
324                 got_dsspooler = True;
325                 for (i=0; i < dsspooler_ctr.num_values; i++)
326                         map_regval_to_ads(mem_ctx, mods, 
327                                           dsspooler_ctr.values[i]);
328         }
329         
330         ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
331
332         if (got_dsdriver) regval_ctr_destroy(&dsdriver_ctr);
333         if (got_dsspooler) regval_ctr_destroy(&dsspooler_ctr);
334         smbcli_spoolss_close_printer(cli, mem_ctx, &pol);
335
336         return result;
337 }
338
339 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
340                                        ADS_MODLIST *mods,
341                                        NT_PRINTER_DATA *data)
342 {
343         uint32_t key,val;
344
345         for (key=0; key < data->num_keys; key++) {
346                 REGVAL_CTR ctr = data->keys[key].values;
347                 for (val=0; val < ctr.num_values; val++)
348                         map_regval_to_ads(mem_ctx, mods, ctr.values[val]);
349         }
350         return True;
351 }
352
353 #endif