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