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