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