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*/ 30ADS_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_add_printer: 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 56ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res) 57{ 58 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*/ 73ADS_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*/ 82ADS_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*/ 92static 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*/ 113static 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 status = ads_mod_str(ctx, mods, value->valuename, str_value); 123 return ADS_ERR_OK(status); 124} 125 126/* 127 map a boolean REG_BINARY to an ldap mod 128*/ 129static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods, 130 const REGISTRY_VALUE *value) 131{ 132 char *str_value; 133 ADS_STATUS status; 134 135 if ((value->type != REG_BINARY) || (value->size != 1)) 136 return False; 137 str_value = talloc_asprintf(ctx, "%s", 138 *(value->data_p) ? "TRUE" : "FALSE"); 139 status = ads_mod_str(ctx, mods, value->valuename, str_value); 140 return ADS_ERR_OK(status); 141} 142 143/* 144 map a REG_MULTI_SZ to an ldap mod 145*/ 146static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 147 const REGISTRY_VALUE *value) 148{ 149 char **str_values = NULL; 150 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p; 151 uint32 size = 0, num_vals = 0, i=0; 152 ADS_STATUS status; 153 154 if (value->type != REG_MULTI_SZ) 155 return False; 156 157 while(cur_str && *cur_str && (size < value->size)) { 158 size += 2 * (strlen_w(cur_str) + 1); 159 cur_str += strlen_w(cur_str) + 1; 160 num_vals++; 161 }; 162 163 if (num_vals) { 164 str_values = talloc(ctx, 165 (num_vals + 1) * sizeof(smb_ucs2_t *)); 166 memset(str_values, '\0', 167 (num_vals + 1) * sizeof(smb_ucs2_t *)); 168 169 cur_str = (smb_ucs2_t *) value->data_p; 170 for (i=0; i < num_vals; i++) 171 cur_str += pull_ucs2_talloc(ctx, &str_values[i], 172 cur_str); 173 174 status = ads_mod_strlist(ctx, mods, value->valuename, 175 (const char **) str_values); 176 return ADS_ERR_OK(status); 177 } 178 return True; 179} 180 181struct valmap_to_ads { 182 const char *valname; 183 BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *); 184}; 185 186/* 187 map a REG_SZ to an ldap mod 188*/ 189static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 190 REGISTRY_VALUE *value) 191{ 192 const struct valmap_to_ads map[] = { 193 {SPOOL_REG_ASSETNUMBER, map_sz}, 194 {SPOOL_REG_BYTESPERMINUTE, map_dword}, 195 {SPOOL_REG_DEFAULTPRIORITY, map_dword}, 196 {SPOOL_REG_DESCRIPTION, map_sz}, 197 {SPOOL_REG_DRIVERNAME, map_sz}, 198 {SPOOL_REG_DRIVERVERSION, map_dword}, 199 {SPOOL_REG_FLAGS, map_dword}, 200 {SPOOL_REG_LOCATION, map_sz}, 201 {SPOOL_REG_OPERATINGSYSTEM, map_sz}, 202 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz}, 203 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz}, 204 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz}, 205 {SPOOL_REG_PORTNAME, map_multi_sz}, 206 {SPOOL_REG_PRINTATTRIBUTES, map_dword}, 207 {SPOOL_REG_PRINTBINNAMES, map_multi_sz}, 208 {SPOOL_REG_PRINTCOLLATE, map_bool}, 209 {SPOOL_REG_PRINTCOLOR, map_bool}, 210 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool}, 211 {SPOOL_REG_PRINTENDTIME, map_dword}, 212 {SPOOL_REG_PRINTFORMNAME, map_sz}, 213 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool}, 214 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz}, 215 {SPOOL_REG_PRINTMACADDRESS, map_sz}, 216 {SPOOL_REG_PRINTMAXCOPIES, map_sz}, 217 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword}, 218 {SPOOL_REG_PRINTMAXXEXTENT, map_dword}, 219 {SPOOL_REG_PRINTMAXYEXTENT, map_dword}, 220 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz}, 221 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz}, 222 {SPOOL_REG_PRINTMEMORY, map_dword}, 223 {SPOOL_REG_PRINTMINXEXTENT, map_dword}, 224 {SPOOL_REG_PRINTMINYEXTENT, map_dword}, 225 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz}, 226 {SPOOL_REG_PRINTNOTIFY, map_sz}, 227 {SPOOL_REG_PRINTNUMBERUP, map_dword}, 228 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz}, 229 {SPOOL_REG_PRINTOWNER, map_sz}, 230 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword}, 231 {SPOOL_REG_PRINTRATE, map_dword}, 232 {SPOOL_REG_PRINTRATEUNIT, map_sz}, 233 {SPOOL_REG_PRINTSEPARATORFILE, map_sz}, 234 {SPOOL_REG_PRINTSHARENAME, map_sz}, 235 {SPOOL_REG_PRINTSPOOLING, map_sz}, 236 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool}, 237 {SPOOL_REG_PRINTSTARTTIME, map_dword}, 238 {SPOOL_REG_PRINTSTATUS, map_sz}, 239 {SPOOL_REG_PRIORITY, map_dword}, 240 {SPOOL_REG_SERVERNAME, map_sz}, 241 {SPOOL_REG_SHORTSERVERNAME, map_sz}, 242 {SPOOL_REG_UNCNAME, map_sz}, 243 {SPOOL_REG_URL, map_sz}, 244 {SPOOL_REG_VERSIONNUMBER, map_dword}, 245 {NULL, NULL} 246 }; 247 int i; 248 249 for (i=0; map[i].valname; i++) { 250 if (StrCaseCmp(map[i].valname, value->valuename) == 0) { 251 if (!map[i].fn(ctx, mods, value)) { 252 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename)); 253 } else { 254 DEBUG(7, ("Mapped value %s\n", value->valuename)); 255 } 256 257 } 258 } 259} 260 261 262WERROR get_remote_printer_publishing_data(struct cli_state *cli, 263 TALLOC_CTX *mem_ctx, 264 ADS_MODLIST *mods, 265 const char *printer) 266{ 267 WERROR result; 268 char *printername, *servername; 269 REGVAL_CTR dsdriver_ctr, dsspooler_ctr; 270 BOOL got_dsdriver = False, got_dsspooler = False; 271 uint32 needed, i; 272 POLICY_HND pol; 273 274 asprintf(&servername, "\\\\%s", cli->desthost); 275 asprintf(&printername, "%s\\%s", servername, printer); 276 if (!servername || !printername) { 277 DEBUG(3, ("Insufficient memory\n")); 278 return WERR_NOMEM; 279 } 280 281 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 282 "", MAXIMUM_ALLOWED_ACCESS, 283 servername, cli->user_name, &pol); 284 if (!W_ERROR_IS_OK(result)) { 285 DEBUG(3, ("Unable to open printer %s, error is %s.\n", 286 printername, dos_errstr(result))); 287 return result; 288 } 289 290 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 291 &pol, SPOOL_DSDRIVER_KEY, NULL); 292 293 if (W_ERROR_V(result) == ERRmoredata) 294 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 295 NULL, &pol, 296 SPOOL_DSDRIVER_KEY, 297 &dsdriver_ctr); 298 299 if (!W_ERROR_IS_OK(result)) { 300 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", 301 printername, dos_errstr(result))); 302 } else { 303 304 /* Have the data we need now, so start building */ 305 got_dsdriver = True; 306 for (i=0; i < dsdriver_ctr.num_values; i++) 307 map_regval_to_ads(mem_ctx, mods, 308 dsdriver_ctr.values[i]); 309 } 310 311 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 312 &pol, SPOOL_DSSPOOLER_KEY, 313 NULL); 314 315 if (W_ERROR_V(result) == ERRmoredata) 316 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 317 NULL, &pol, 318 SPOOL_DSSPOOLER_KEY, 319 &dsspooler_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 got_dsspooler = True; 326 for (i=0; i < dsspooler_ctr.num_values; i++) 327 map_regval_to_ads(mem_ctx, mods, 328 dsspooler_ctr.values[i]); 329 } 330 331 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer); 332 333 if (got_dsdriver) regval_ctr_destroy(&dsdriver_ctr); 334 if (got_dsspooler) regval_ctr_destroy(&dsspooler_ctr); 335 cli_spoolss_close_printer(cli, mem_ctx, &pol); 336 337 return result; 338} 339 340BOOL 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 355