b2ee5f22655120aeb6d1c516d857c43c39ee21cc
[tprouty/samba.git] / source / 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, *exp;
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(&exp, "(cn=%s-%s)", srv_cn[0], printer);
48         status = ads_search(ads, res, exp, attrs);
49
50         ldap_memfree(srv_dn);
51         ldap_value_free(srv_cn);
52         free(exp);
53         return status;  
54 }
55
56 /*
57   modify a printer entry in the directory
58 */
59 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
60                                  TALLOC_CTX *ctx, const ADS_MODLIST *mods)
61 {
62         return ads_gen_mod(ads, prt_dn, *mods);
63 }
64
65 /*
66   add a printer to the directory
67 */
68 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
69                                         TALLOC_CTX *ctx, ADS_MODLIST *mods)
70 {
71         ads_mod_str(ctx, mods, "objectClass", "printQueue");
72         return ads_gen_add(ads, prt_dn, *mods);
73 }
74
75 /*
76   map a REG_SZ to an ldap mod
77 */
78 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
79                             const REGISTRY_VALUE *value)
80 {
81         char *str_value = NULL;
82         ADS_STATUS status;
83
84         if (value->type != REG_SZ)
85                 return False;
86
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);
92         }
93         return True;
94                 
95 }
96
97 /*
98   map a REG_DWORD to an ldap mod
99 */
100 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
101                       const REGISTRY_VALUE *value)
102 {
103         char *str_value = NULL;
104         ADS_STATUS status;
105
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);
111 }
112
113 /*
114   map a boolean REG_BINARY to an ldap mod
115 */
116 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
117                      const REGISTRY_VALUE *value)
118 {
119         char *str_value;
120         ADS_STATUS status;
121
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);
128 }
129
130 /*
131   map a REG_MULTI_SZ to an ldap mod
132 */
133 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
134                          const REGISTRY_VALUE *value)
135 {
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;
140
141         if (value->type != REG_MULTI_SZ)
142                 return False;
143
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++;
148         };
149
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 *));
155
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);
161
162                 status = ads_mod_strlist(ctx, mods, value->valuename, 
163                                          (const char **) str_values);
164                 return ADS_ERR_OK(status);
165         } 
166         return True;
167 }
168
169 struct valmap_to_ads {
170         char *valname;
171         BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
172 };
173
174 /*
175   map a REG_SZ to an ldap mod
176 */
177 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
178                               REGISTRY_VALUE *value)
179 {
180         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}
234         };
235         int i;
236
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));
243                         }
244                         
245                 }
246         }
247 }
248
249
250 WERROR get_remote_printer_publishing_data(struct cli_state *cli, 
251                                           TALLOC_CTX *mem_ctx,
252                                           ADS_MODLIST *mods,
253                                           char *printer)
254 {
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;
261
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;
267         }
268         
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;
276         }
277         
278         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
279                                                &pol, SPOOL_DSDRIVER_KEY, NULL);
280
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);
286
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 {
291
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]);
297         }
298         
299         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
300                                                &pol, SPOOL_DSSPOOLER_KEY, 
301                                                NULL);
302
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);
308
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]);
317         }
318         
319         ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
320
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);
324
325         return result;
326 }
327
328 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
329                                        ADS_MODLIST *mods,
330                                        NT_PRINTER_DATA *data)
331 {
332         uint32 key,val;
333
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]);
338         }
339         return True;
340 }
341
342 #endif
343