s3:libsmb: inline trust_pw_change_and_store_it() into trust_pw_find_change_and_store_it()
[mat/samba.git] / source3 / printing / nt_printing_ads.c
index c5e3f99fb62cffa25059cfa901095a91137960b8..5d5f5646da59342fdada8c5c09b36509dde9b650 100644 (file)
@@ -39,7 +39,7 @@ static void store_printer_guid(struct messaging_context *msg_ctx,
                               const char *printer, struct GUID guid)
 {
        TALLOC_CTX *tmp_ctx;
-       struct auth_serversupplied_info *session_info = NULL;
+       struct auth_session_info *session_info = NULL;
        const char *guid_str;
        DATA_BLOB blob;
        NTSTATUS status;
@@ -87,6 +87,160 @@ done:
        talloc_free(tmp_ctx);
 }
 
+WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
+                          const struct auth_session_info *session_info,
+                          struct messaging_context *msg_ctx,
+                          const char *printer, struct GUID *guid)
+{
+       TALLOC_CTX *tmp_ctx;
+       enum winreg_Type type;
+       DATA_BLOB blob;
+       uint32_t len;
+       NTSTATUS status;
+       WERROR result;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
+               DEBUG(0, ("out of memory?!\n"));
+               return WERR_NOMEM;
+       }
+
+       result = winreg_get_printer_dataex_internal(tmp_ctx, session_info,
+                                                   msg_ctx, printer,
+                                                   SPOOL_DSSPOOLER_KEY,
+                                                   "objectGUID",
+                                                   &type,
+                                                   &blob.data,
+                                                   &len);
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("Failed to get GUID for printer %s\n", printer));
+               goto out_ctx_free;
+       }
+       blob.length = (size_t)len;
+
+       /* We used to store the guid as REG_BINARY, then swapped
+          to REG_SZ for Vista compatibility so check for both */
+
+       switch (type) {
+       case REG_SZ: {
+               bool ok;
+               const char *guid_str;
+               ok = pull_reg_sz(tmp_ctx, &blob, &guid_str);
+               if (!ok) {
+                       DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
+                                 printer));
+                       result = WERR_REG_CORRUPT;
+                       goto out_ctx_free;
+               }
+               status = GUID_from_string(guid_str, guid);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("bad GUID for printer %s\n", printer));
+                       result = ntstatus_to_werror(status);
+                       goto out_ctx_free;
+               }
+               break;
+       }
+       case REG_BINARY:
+               if (blob.length != sizeof(struct GUID)) {
+                       DEBUG(0, ("bad GUID for printer %s\n", printer));
+                       result = WERR_REG_CORRUPT;
+                       goto out_ctx_free;
+               }
+               memcpy(guid, blob.data, sizeof(struct GUID));
+               break;
+       default:
+               DEBUG(0,("GUID value stored as invalid type (%d)\n", type));
+               result = WERR_REG_CORRUPT;
+               goto out_ctx_free;
+               break;
+       }
+       result = WERR_OK;
+
+out_ctx_free:
+       talloc_free(tmp_ctx);
+       return result;
+}
+
+static WERROR nt_printer_info_to_mods(TALLOC_CTX *ctx,
+                                     struct spoolss_PrinterInfo2 *info2,
+                                     ADS_MODLIST *mods)
+{
+       char *info_str;
+
+       ads_mod_str(ctx, mods, SPOOL_REG_PRINTERNAME, info2->sharename);
+       ads_mod_str(ctx, mods, SPOOL_REG_SHORTSERVERNAME, lp_netbios_name());
+       ads_mod_str(ctx, mods, SPOOL_REG_SERVERNAME, get_mydnsfullname());
+
+       info_str = talloc_asprintf(ctx, "\\\\%s\\%s",
+                                  get_mydnsfullname(), info2->sharename);
+       if (info_str == NULL) {
+               return WERR_NOMEM;
+       }
+       ads_mod_str(ctx, mods, SPOOL_REG_UNCNAME, info_str);
+
+       info_str = talloc_asprintf(ctx, "%d", 4);
+       if (info_str == NULL) {
+               return WERR_NOMEM;
+       }
+       ads_mod_str(ctx, mods, SPOOL_REG_VERSIONNUMBER, info_str);
+
+       /* empty strings in the mods list result in an attrubute error */
+       if (strlen(info2->drivername) != 0)
+               ads_mod_str(ctx, mods, SPOOL_REG_DRIVERNAME, info2->drivername);
+       if (strlen(info2->location) != 0)
+               ads_mod_str(ctx, mods, SPOOL_REG_LOCATION, info2->location);
+       if (strlen(info2->comment) != 0)
+               ads_mod_str(ctx, mods, SPOOL_REG_DESCRIPTION, info2->comment);
+       if (strlen(info2->portname) != 0)
+               ads_mod_str(ctx, mods, SPOOL_REG_PORTNAME, info2->portname);
+       if (strlen(info2->sepfile) != 0)
+               ads_mod_str(ctx, mods, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
+
+       info_str = talloc_asprintf(ctx, "%u", info2->starttime);
+       if (info_str == NULL) {
+               return WERR_NOMEM;
+       }
+       ads_mod_str(ctx, mods, SPOOL_REG_PRINTSTARTTIME, info_str);
+
+       info_str = talloc_asprintf(ctx, "%u", info2->untiltime);
+       if (info_str == NULL) {
+               return WERR_NOMEM;
+       }
+       ads_mod_str(ctx, mods, SPOOL_REG_PRINTENDTIME, info_str);
+
+       info_str = talloc_asprintf(ctx, "%u", info2->priority);
+       if (info_str == NULL) {
+               return WERR_NOMEM;
+       }
+       ads_mod_str(ctx, mods, SPOOL_REG_PRIORITY, info_str);
+
+       if (info2->attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) {
+               ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "TRUE");
+       } else {
+               ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "FALSE");
+       }
+
+       switch (info2->attributes & 0x3) {
+       case 0:
+               ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
+                           SPOOL_REGVAL_PRINTWHILESPOOLING);
+               break;
+       case 1:
+               ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
+                           SPOOL_REGVAL_PRINTAFTERSPOOLED);
+               break;
+       case 2:
+               ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
+                           SPOOL_REGVAL_PRINTDIRECT);
+               break;
+       default:
+               DEBUG(3, ("unsupported printer attributes %x\n",
+                         info2->attributes));
+       }
+
+       return WERR_OK;
+}
+
 static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
                                     ADS_STRUCT *ads,
                                     struct spoolss_PrinterInfo2 *pinfo2)
@@ -112,17 +266,23 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
        DEBUG(5, ("publishing printer %s\n", printer));
 
        /* figure out where to publish */
-       ads_find_machine_acct(ads, &res, lp_netbios_name());
+       ads_rc = ads_find_machine_acct(ads, &res, lp_netbios_name());
+       if (!ADS_ERR_OK(ads_rc)) {
+               DEBUG(0, ("failed to find machine account for %s\n",
+                         lp_netbios_name()));
+               TALLOC_FREE(ctx);
+               return WERR_NOT_FOUND;
+       }
 
        /* We use ldap_get_dn here as we need the answer
         * in utf8 to call ldap_explode_dn(). JRA. */
 
        srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
+       ads_msgfree(ads, res);
        if (!srv_dn_utf8) {
                TALLOC_FREE(ctx);
                return WERR_SERVER_UNAVAILABLE;
        }
-       ads_msgfree(ads, res);
        srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
        if (!srv_cn_utf8) {
                TALLOC_FREE(ctx);
@@ -167,12 +327,15 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
        mods = ads_init_mods(ctx);
 
        if (mods == NULL) {
-               SAFE_FREE(prt_dn);
                TALLOC_FREE(ctx);
                return WERR_NOMEM;
        }
 
-       ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
+       win_rc = nt_printer_info_to_mods(ctx, pinfo2, &mods);
+       if (!W_ERROR_IS_OK(win_rc)) {
+               TALLOC_FREE(ctx);
+               return win_rc;
+       }
 
        /* publish it */
        ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
@@ -244,7 +407,7 @@ static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
  ***************************************************************************/
 
 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
-                         const struct auth_serversupplied_info *session_info,
+                         const struct auth_session_info *session_info,
                          struct messaging_context *msg_ctx,
                          struct spoolss_PrinterInfo2 *pinfo2,
                          int action)
@@ -254,6 +417,7 @@ WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
        ADS_STATUS ads_rc;
        ADS_STRUCT *ads = NULL;
        WERROR win_rc;
+       char *old_krb5ccname = NULL;
 
        sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
        if (!sinfo2) {
@@ -266,7 +430,7 @@ WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
                pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
                break;
        case DSPRINT_UNPUBLISH:
-               pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
+               pinfo2->attributes &= (~PRINTER_ATTRIBUTE_PUBLISHED);
                break;
        default:
                win_rc = WERR_NOT_SUPPORTED;
@@ -291,6 +455,7 @@ WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
                win_rc = WERR_SERVER_UNAVAILABLE;
                goto done;
        }
+       old_krb5ccname = getenv(KRB5_ENV_CCNAME);
        setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
        SAFE_FREE(ads->auth.password);
        ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
@@ -316,6 +481,11 @@ WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
 
 done:
        ads_destroy(&ads);
+       ads_kdestroy("MEMORY:prtpub_cache");
+       unsetenv(KRB5_ENV_CCNAME);
+       if (old_krb5ccname) {
+               setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
+       }
        return win_rc;
 }
 
@@ -326,10 +496,11 @@ WERROR check_published_printers(struct messaging_context *msg_ctx)
        int snum;
        int n_services = lp_numservices();
        TALLOC_CTX *tmp_ctx = NULL;
-       struct auth_serversupplied_info *session_info = NULL;
+       struct auth_session_info *session_info = NULL;
        struct spoolss_PrinterInfo2 *pinfo2;
        NTSTATUS status;
        WERROR result;
+       char *old_krb5ccname = NULL;
 
        tmp_ctx = talloc_new(NULL);
        if (!tmp_ctx) return WERR_NOMEM;
@@ -339,6 +510,7 @@ WERROR check_published_printers(struct messaging_context *msg_ctx)
                DEBUG(3, ("ads_init() failed\n"));
                return WERR_SERVER_UNAVAILABLE;
        }
+       old_krb5ccname = getenv(KRB5_ENV_CCNAME);
        setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
        SAFE_FREE(ads->auth.password);
        ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
@@ -366,7 +538,7 @@ WERROR check_published_printers(struct messaging_context *msg_ctx)
                }
 
                result = winreg_get_printer_internal(tmp_ctx, session_info, msg_ctx,
-                                           lp_servicename(snum),
+                                           lp_servicename(talloc_tos(), snum),
                                            &pinfo2);
                if (!W_ERROR_IS_OK(result)) {
                        continue;
@@ -383,75 +555,44 @@ WERROR check_published_printers(struct messaging_context *msg_ctx)
 done:
        ads_destroy(&ads);
        ads_kdestroy("MEMORY:prtpub_cache");
+       unsetenv(KRB5_ENV_CCNAME);
+       if (old_krb5ccname) {
+               setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
+       }
        talloc_free(tmp_ctx);
        return result;
 }
 
 bool is_printer_published(TALLOC_CTX *mem_ctx,
-                         const struct auth_serversupplied_info *session_info,
+                         const struct auth_session_info *session_info,
                          struct messaging_context *msg_ctx,
-                         const char *servername, char *printer, struct GUID *guid,
+                         const char *servername,
+                         const char *printer,
                          struct spoolss_PrinterInfo2 **info2)
 {
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
-       enum winreg_Type type;
-       uint8_t *data;
-       uint32_t data_size;
        WERROR result;
-       NTSTATUS status;
+       struct dcerpc_binding_handle *b;
 
-       result = winreg_get_printer_internal(mem_ctx, session_info, msg_ctx,
-                                   printer, &pinfo2);
+       result = winreg_printer_binding_handle(mem_ctx,
+                                              session_info,
+                                              msg_ctx,
+                                              &b);
        if (!W_ERROR_IS_OK(result)) {
                return false;
        }
 
-       if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
-               TALLOC_FREE(pinfo2);
+       result = winreg_get_printer(mem_ctx, b,
+                                   printer, &pinfo2);
+       if (!W_ERROR_IS_OK(result)) {
                return false;
        }
 
-       if (!guid) {
-               goto done;
-       }
-
-       /* fetching printer guids really ought to be a separate function. */
-
-       result = winreg_get_printer_dataex_internal(mem_ctx, session_info, msg_ctx,
-                                          printer,
-                                          SPOOL_DSSPOOLER_KEY, "objectGUID",
-                                          &type, &data, &data_size);
-       if (!W_ERROR_IS_OK(result)) {
+       if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
                TALLOC_FREE(pinfo2);
                return false;
        }
 
-       /* We used to store the guid as REG_BINARY, then swapped
-          to REG_SZ for Vista compatibility so check for both */
-
-       switch (type) {
-       case REG_SZ:
-               status = GUID_from_string((char *)data, guid);
-               if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(pinfo2);
-                       return false;
-               }
-               break;
-
-       case REG_BINARY:
-               if (data_size != sizeof(struct GUID)) {
-                       TALLOC_FREE(pinfo2);
-                       return false;
-               }
-               memcpy(guid, data, sizeof(struct GUID));
-               break;
-       default:
-               DEBUG(0,("is_printer_published: GUID value stored as "
-                        "invaluid type (%d)\n", type));
-               break;
-       }
-
-done:
        if (info2) {
                *info2 = talloc_move(mem_ctx, &pinfo2);
        }
@@ -459,8 +600,16 @@ done:
        return true;
 }
 #else
+WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
+                          const struct auth_session_info *session_info,
+                          struct messaging_context *msg_ctx,
+                          const char *printer, struct GUID *guid)
+{
+       return WERR_NOT_SUPPORTED;
+}
+
 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
-                         const struct auth_serversupplied_info *session_info,
+                         const struct auth_session_info *session_info,
                          struct messaging_context *msg_ctx,
                          struct spoolss_PrinterInfo2 *pinfo2,
                          int action)
@@ -474,9 +623,10 @@ WERROR check_published_printers(struct messaging_context *msg_ctx)
 }
 
 bool is_printer_published(TALLOC_CTX *mem_ctx,
-                         const struct auth_serversupplied_info *session_info,
+                         const struct auth_session_info *session_info,
                          struct messaging_context *msg_ctx,
-                         const char *servername, char *printer, struct GUID *guid,
+                         const char *servername,
+                         const char *printer,
                          struct spoolss_PrinterInfo2 **info2)
 {
        return False;