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