s3-param: Rename loadparm_s3_context -> loadparm_s3_helpers
[kai/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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "ads.h"
22 #include "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "rpc_client/cli_spoolss.h"
25 #include "registry.h"
26 #include "libcli/registry/util_reg.h"
27
28 #ifdef HAVE_ADS
29
30 /*
31   find a printer given the name and the hostname
32     Note that results "res" may be allocated on return so that the
33     results can be used.  It should be freed using ads_msgfree.
34 */
35  ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
36                                        const char *printer,
37                                        const char *servername)
38 {
39         ADS_STATUS status;
40         char *srv_dn, **srv_cn, *s = NULL;
41         const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
42
43         status = ads_find_machine_acct(ads, res, servername);
44         if (!ADS_ERR_OK(status)) {
45                 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
46                           servername));
47                 return status;
48         }
49         if (ads_count_replies(ads, *res) != 1) {
50                 ads_msgfree(ads, *res);
51                 *res = NULL;
52                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
53         }
54         srv_dn = ldap_get_dn(ads->ldap.ld, *res);
55         if (srv_dn == NULL) {
56                 ads_msgfree(ads, *res);
57                 *res = NULL;
58                 return ADS_ERROR(LDAP_NO_MEMORY);
59         }
60         srv_cn = ldap_explode_dn(srv_dn, 1);
61         if (srv_cn == NULL) {
62                 ldap_memfree(srv_dn);
63                 ads_msgfree(ads, *res);
64                 *res = NULL;
65                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
66         }
67         ads_msgfree(ads, *res);
68         *res = NULL;
69
70         if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
71                 ldap_memfree(srv_dn);
72                 return ADS_ERROR(LDAP_NO_MEMORY);
73         }
74         status = ads_search(ads, res, s, attrs);
75
76         ldap_memfree(srv_dn);
77         ldap_value_free(srv_cn);
78         SAFE_FREE(s);
79         return status;  
80 }
81
82  ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
83 {
84         const char *ldap_expr;
85         const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
86                                 "serverName", "description", NULL };
87
88         /* For the moment only display all printers */
89
90         ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
91                 "(objectCategory=printQueue))";
92
93         return ads_search(ads, res, ldap_expr, attrs);
94 }
95
96 /*
97   modify a printer entry in the directory
98 */
99 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
100                                  TALLOC_CTX *ctx, const ADS_MODLIST *mods)
101 {
102         return ads_gen_mod(ads, prt_dn, *mods);
103 }
104
105 /*
106   add a printer to the directory
107 */
108 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
109                                         TALLOC_CTX *ctx, ADS_MODLIST *mods)
110 {
111         ads_mod_str(ctx, mods, "objectClass", "printQueue");
112         return ads_gen_add(ads, prt_dn, *mods);
113 }
114
115 /*
116   map a REG_SZ to an ldap mod
117 */
118 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
119                    const char *name, struct registry_value *value)
120 {
121         const char *str_value = NULL;
122         ADS_STATUS status;
123
124         if (value->type != REG_SZ)
125                 return false;
126
127         if (value->data.length  && value->data.data) {
128                 if (!pull_reg_sz(ctx, &value->data, &str_value)) {
129                         return false;
130                 }
131                 status = ads_mod_str(ctx, mods, name, str_value);
132                 return ADS_ERR_OK(status);
133         }
134         return true;
135 }
136
137 /*
138   map a REG_DWORD to an ldap mod
139 */
140 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
141                       const char *name, struct registry_value *value)
142 {
143         char *str_value = NULL;
144         ADS_STATUS status;
145
146         if (value->type != REG_DWORD) {
147                 return false;
148         }
149         if (value->data.length != sizeof(uint32)) {
150                 return false;
151         }
152         str_value = talloc_asprintf(ctx, "%d", IVAL(value->data.data, 0));
153         if (!str_value) {
154                 return false;
155         }
156         status = ads_mod_str(ctx, mods, name, str_value);
157         return ADS_ERR_OK(status);
158 }
159
160 /*
161   map a boolean REG_BINARY to an ldap mod
162 */
163 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
164                      const char *name, struct registry_value *value)
165 {
166         const char *str_value;
167         ADS_STATUS status;
168
169         if (value->type != REG_BINARY) {
170                 return false;
171         }
172         if (value->data.length != 1) {
173                 return false;
174         }
175
176         str_value =  *value->data.data ? "TRUE" : "FALSE";
177
178         status = ads_mod_str(ctx, mods, name, str_value);
179         return ADS_ERR_OK(status);
180 }
181
182 /*
183   map a REG_MULTI_SZ to an ldap mod
184 */
185 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
186                          const char *name, struct registry_value *value)
187 {
188         const char **str_values = NULL;
189         ADS_STATUS status;
190
191         if (value->type != REG_MULTI_SZ) {
192                 return false;
193         }
194
195         if (value->data.length  && value->data.data) {
196                 if (!pull_reg_multi_sz(ctx, &value->data, &str_values)) {
197                         return false;
198                 }
199                 status = ads_mod_strlist(ctx, mods, name, str_values);
200                 return ADS_ERR_OK(status);
201         }
202         return true;
203 }
204
205 struct valmap_to_ads {
206         const char *valname;
207         bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const char *, struct registry_value *);
208 };
209
210 /*
211   map a REG_SZ to an ldap mod
212 */
213 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
214                               const char *name, struct registry_value *value)
215 {
216         const struct valmap_to_ads map[] = {
217                 {SPOOL_REG_ASSETNUMBER, map_sz},
218                 {SPOOL_REG_BYTESPERMINUTE, map_dword},
219                 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
220                 {SPOOL_REG_DESCRIPTION, map_sz},
221                 {SPOOL_REG_DRIVERNAME, map_sz},
222                 {SPOOL_REG_DRIVERVERSION, map_dword},
223                 {SPOOL_REG_FLAGS, map_dword},
224                 {SPOOL_REG_LOCATION, map_sz},
225                 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
226                 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
227                 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
228                 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
229                 {SPOOL_REG_PORTNAME, map_multi_sz},
230                 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
231                 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
232                 {SPOOL_REG_PRINTCOLLATE, map_bool},
233                 {SPOOL_REG_PRINTCOLOR, map_bool},
234                 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
235                 {SPOOL_REG_PRINTENDTIME, map_dword},
236                 {SPOOL_REG_PRINTFORMNAME, map_sz},
237                 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
238                 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
239                 {SPOOL_REG_PRINTMACADDRESS, map_sz},
240                 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
241                 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
242                 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
243                 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
244                 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
245                 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
246                 {SPOOL_REG_PRINTMEMORY, map_dword},
247                 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
248                 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
249                 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
250                 {SPOOL_REG_PRINTNOTIFY, map_sz},
251                 {SPOOL_REG_PRINTNUMBERUP, map_dword},
252                 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
253                 {SPOOL_REG_PRINTOWNER, map_sz},
254                 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
255                 {SPOOL_REG_PRINTRATE, map_dword},
256                 {SPOOL_REG_PRINTRATEUNIT, map_sz},
257                 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
258                 {SPOOL_REG_PRINTSHARENAME, map_sz},
259                 {SPOOL_REG_PRINTSPOOLING, map_sz},
260                 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
261                 {SPOOL_REG_PRINTSTARTTIME, map_dword},
262                 {SPOOL_REG_PRINTSTATUS, map_sz},
263                 {SPOOL_REG_PRIORITY, map_dword},
264                 {SPOOL_REG_SERVERNAME, map_sz},
265                 {SPOOL_REG_SHORTSERVERNAME, map_sz},
266                 {SPOOL_REG_UNCNAME, map_sz},
267                 {SPOOL_REG_URL, map_sz},
268                 {SPOOL_REG_VERSIONNUMBER, map_dword},
269                 {NULL, NULL}
270         };
271         int i;
272
273         for (i=0; map[i].valname; i++) {
274                 if (strcasecmp_m(map[i].valname, name) == 0) {
275                         if (!map[i].fn(ctx, mods, name, value)) {
276                                 DEBUG(5, ("Add of value %s to modlist failed\n", name));
277                         } else {
278                                 DEBUG(7, ("Mapped value %s\n", name));
279                         }
280                 }
281         }
282 }
283
284
285 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli, 
286                                           TALLOC_CTX *mem_ctx,
287                                           ADS_MODLIST *mods,
288                                           const char *printer)
289 {
290         struct dcerpc_binding_handle *b = cli->binding_handle;
291         WERROR result;
292         char *printername;
293         struct spoolss_PrinterEnumValues *info;
294         uint32_t count;
295         uint32 i;
296         struct policy_handle pol;
297         WERROR werr;
298
299         if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
300                 DEBUG(3, ("Insufficient memory\n"));
301                 return WERR_NOMEM;
302         }
303
304         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
305                                                printername,
306                                                SEC_FLAG_MAXIMUM_ALLOWED,
307                                                &pol);
308         if (!W_ERROR_IS_OK(result)) {
309                 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
310                           printername, win_errstr(result)));
311                 SAFE_FREE(printername);
312                 return result;
313         }
314
315         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
316                                                   SPOOL_DSDRIVER_KEY,
317                                                   0,
318                                                   &count,
319                                                   &info);
320
321         if (!W_ERROR_IS_OK(result)) {
322                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
323                           printername, win_errstr(result)));
324         } else {
325                 /* Have the data we need now, so start building */
326                 for (i=0; i < count; i++) {
327                         struct registry_value v;
328                         v.type = info[i].type;
329                         v.data = *info[i].data;
330
331                         map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
332                 }
333         }
334
335         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
336                                                   SPOOL_DSSPOOLER_KEY,
337                                                   0,
338                                                   &count,
339                                                   &info);
340         if (!W_ERROR_IS_OK(result)) {
341                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
342                           printername, win_errstr(result)));
343         } else {
344                 for (i=0; i < count; i++) {
345                         struct registry_value v;
346                         v.type = info[i].type;
347                         v.data = *info[i].data;
348
349                         map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
350                 }
351         }
352
353         ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
354
355         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr);
356         SAFE_FREE(printername);
357
358         return result;
359 }
360
361 #endif