root/source3/libads/ldap_printer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ads_find_printer_on_server
  2. ads_find_printers
  3. ads_mod_printer_entry
  4. ads_add_printer_entry
  5. map_sz
  6. map_dword
  7. map_bool
  8. map_multi_sz
  9. map_regval_to_ads
  10. get_remote_printer_publishing_data
  11. get_local_printer_publishing_data

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

/* [<][>][^][v][top][bottom][index][help] */