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