IIS mit PHP Berechtigungsfehler beim Upload von Dateien

Unter Windows mit einem IIS und PHP habe ich soeben STUNDEN damit zugebracht, herauszufinden warum meine hochgeladenen Bilder (und Dateien) nicht die erforderlichen Berechtigungen für eine korrekte Anzeige aus dem Upload-Ordner erben. „Serverfehler 500“ sagt der IIS dazu ja auch nur und Bilder werden nicht angezeigt.

Das Problem tritt nur auf, wenn man PHP zum Hochladen nutzt. .NET hat das Problem generell nicht.

PHP legt hochgeladene Dateien nämlich in einem temporären Verzeichnis ab (Default: %windir%\Temp) und VERSCHIEBT diese danach ins Zielverzeichnis. Wenn eine Datei in dem temporären Upload-Verzeichnis angekommen ist, erbt sie (korrekterweise) erst einmal die NTFS-Berechtigungen dieses Verzeichnisses. Verschieben der Datei auf dem selben Laufwerk erhält dann aber die Berechtigungen dieser Datei und diese erbt die Berechtigungen des Ziel-Webverzeichnisses nicht. Verschiebt man über Volumengrenzen hinweg, tritt dieser Fehler nicht auf: Neue Dateien erben dort die NTFS-Berechtigungen des Zielordners. Das ist so, weil verschiebeoperationen eines Volumes nur den Pointer einer Datei ändern, die anhängenden ACLs und Metadaten aber nicht.

Lösung

Der einfachste Weg dieses Problem zu beheben besteht darin, die Berechtigungen der Ziel-Webverzeichnisses auf das temporäre Upload-Verzeichnis zu übertragen, bzw. die ACLs zu ergänzen. Einfach die Berechtigungen des Webverzeichnisses zum TEMP-Verzeichnis hinzufügen.

  1. Das temporäre Upload-Verzeichnisses in der php.ini-Datei in dem Parameter „upload_tmp_dir“ festgelegt. Ist kein Eintrag festgelegt, verwendet PHP %TEMP%
  2. In diesem Ordner alle Berechtigungen des Ziel-Webordners hinzufügen.

Windows 8/10: DNS-Namensauflösung über VPN-Verbindung erzwingen

Ein weit verbreitetes Problem bei Windows VPN-Verbindungen (RAS/RRAS) ist das Erzwingen der DNS-Namensauflösung über den VPN-Tunnel. Unter Windows ab Version 8 versucht Windows „smart“ zu sein und vermeintlich externe Domains über den Standart-Resovler aufzulösen.

Daher funktioniert die Namensauflösung für VPN-Clients of nicht korrekt und interne Ressourcen sind nicht erreichbar oder werden falsch aufgelöst.

Der Trick an der Sache: Standardmäßig verwendet Windows ab 10 die Routen- sowie Schnittstellenmetrik nicht mehr ausschliesslich für die Route zu einem Paket-Ziel, sondern auch für die Auswahl des „besten“ DNS-Resolvers. Sofern es nur um eine Verbindung geht klappt das ja auch ganz gut.

Lösung

Man vergibt für die VPN-Schnittstelle einfach eine kleinere Metric. Eine deutlich kleinere als die Schnittstelle der LAN-Verbindung hat (Default: ‚Automatisch‘, normalerweise zwischen 280 und 3800).

Start > Einstellungen > Netzwerk und Internet > Adapteroptionen ändern > VPN-Verbindung auswählen > Eigenschaften > Tab „Netzwerk“ > Eigenschaften > Erweitert > „Schnittstellenmetrik“. Hier etwas kleines eintragen, zum Beispiel „5“.

Nach dem erneuten einwöhlen klappt’s auch mit der Namensauflösung.

Quelle: Sehr tief vergrabener Technet-Artikel unter https://blogs.technet.microsoft.com/networking/2015/08/14/adjusting-the-network-protocol-bindings-in-windows-10/

„Diese Kopie von Microsoft Office kann auf einem Computer, der die Terminaldienste ausführt, nicht verwendet werden.“ mit Office 365 ProPlus

Trotz korrekter Terminalserver-Installation kommt es seit Ende der Jahres 2018 unter Windows Server 2016 in einer RDS-Umgebung häufiger zu diesem Fehler beim Start der Office-Anwendungen:

Diese Kopie von Microsoft Office kann auf einem Computer, der die Terminaldienste ausführt, nicht verwendet werden. Damit Microsoft Office auf einem Computer, der die Terminaldienste ausführt, verwendet werden kann, müssen Sie eine Volumenlizenzedition von Office verwenden.
Diese Kopie von Microsoft Office kann auf einem Computer, der die Terminaldienste ausführt, nicht verwendet werden. Damit Microsoft Office auf einem Computer, der die Terminaldienste ausführt, verwendet werden kann, müssen Sie eine Volumenlizenzedition von Office verwenden.

Der Inhalt dieser Meldung ist mit Office ProPlus natürlich Unsinn und nur ein Überbleibsel aus vergangenen Tagen. Office ProPlus (oder auch „O365ProPlusRetail“) dürfen durchaus in RDS-Umgebungen genutzt werden.

Eigentlich sorgt bei der Installation der Klick-und-Los Variante („setup /configure“) der Eintrag „SharedComputerLicensing“ in der XML-Datei für die richtige Konfiguration; das scheint aber nicht immer so richtig zu klappen. Vor allem unter Office 2019 (das nur Office365 heißt) ist das der Fall – vermutlich weil sich der zugehörige Registry-Schlüssel geändert hat. Früher wohnte dieser in Office\<version>\ClickToRun, nun entfällt <version>.

„Richtige“ Bereitstellungsdatei

<Configuration>
  <Add OfficeClientEdition="32" Channel="Monthly">
    <Product ID="O365ProPlusRetail">
      <Language ID="de-de" />
    </Product>
  </Add>
<Updates Enabled="TRUE" Channel="Monthly" />
<Display Level="NONE" AcceptEULA="TRUE" />
<Property Name="AUTOACTIVATE" Value="1" />
<Property Name="SharedComputerLicensing" Value="1" />  <--_HIER____
</Configuration>

Lösung

Wenn das mal wieder nicht so recht geklappt zu haen scheint, kann man den notwendigen Registry-Eintrag jederzeiot von Hand hinzufügen und schon ist Office wieder Terminalserver-Fähig.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration
   Name: SharedComputerLicensing
   Typ: REG_SZ ("Zeichenfolge")
   Inhalt: 1

Es ist kein reboot notwendig, nach einem Neustart der Anwendungen läuft Office ohne Fehler.

Windows Server 2019 Aktivierung – Der eingegebene Produkt Key funktioniert nicht (0x80070490)

Problem:

Man hat gerade frisch aus dem VLSC das Windows Server 2019 ISO heruntergeladen und möchte die installierte Maschine nun mit dem zugehörigen MAK-Schlüssel aktivieren.

Nach Eingabe des Keys zeigt einem der Aktivierungsassistent allerdings nur die Fehlermeldung:

Der eingegebene Produkt Key funktioniert nicht. Überprüfen Sie den Produkt Key, und versuchen Sie es noch einmal, oder geben Sie einen anderen Produkt Key ein. (0x80070490)

Produkt Key Assistent

Lösung:

Es gibt wohl einen Bug in dem Grafischen Produkt Key Assistenten. Man muss den Key entweder bereits während der Installation angeben oder an der Konsole per slmgr installieren:

slmgr /ipk AAAAA-BBBBB-CCCCC-DDDDD-EEEEE

Danach könnte es noch einen Moment dauern, bis die Aktivierung in den Windows Einstellungen auch korrekt angezeigt wird. Von eventuellen Fehlermeldungen, welche dort direkt nach der Key-Installation angezeigt werden, sollte man sich also zunächst nicht irritieren lassen.

Server 2016/Windows 10 Software im „Abgesicherten Modus“ deinstallieren

Problem

Programme im abgesicherten Modus deinstallieren ist, interessanterweise, nicht ohne weiteres möglich. Wenn man bedenkt das über 90% aller Windows-Abstürze die so eine Operation notwendig machen durch (AV)Software entsteht eine sehr seltsame Desingentscheidung … aber nunja. Wie entfernt man nun Progamme im „Abgesicherten Modus“?

Lösung

  1. Windows im „Abgesicherten Modus“ starten
  2. Unter HKLM/SYSTEM/CurrentControlSet/Control/SafeBoot/Minimal einen neuen Schlüssel mit dem Namen „MSIService“ erstellen
  3. Darin Schlüssel „(Standard)“-Wert auf „Service“ umstellen

Der Schlüssel Minimal enthält die Liste der Treiber und Dienste, die im Abgesicherten Modus zur Verfügung stehen. Nach einem Neustart (oder einem manuellen Dienststart) ist es wieder möglich, programme zu deinstallieren.

Der Schlüssel „network“ beinhaltet übrigend selbiges, nur für den „Abgesicherten Modus mit Netzwerk“.

SQL Express 2012/2014 Windows Authentifizierung nach crash zurücksetzen

Problem

Der Microsoft SQL Server Express Edition ist sehr praktisch, aber leider nach der Installation auch leicht zu übersehen. Nach einem Domänenwechsel, Domänen-Autritt oder einem Crash (der zum Verlust der Anmeldekonten führte) ist eine SQL-Express-Instanz nicht mehr zugänglich. Standardmäßig sind nur Windows-Anmeldungen erlaubt, die es nun ja nicht mehr gibt.

„Zugriff verweigert“ oder „Access to Database denied“ lauten die Fehlermeldungen dazu.

Lösung

Man kann die Authentifizierung im SQLEE insofern zurücksetzen, als das man sein eigenes Anmeldekonto (sofern administrativ) zum SYSADMIN in der Datenbankinstanz macht. Dann kann mann sich wieder anmelden, die Rechte zurücksetzen und seine Datenbanken richtig konfigurieren.

Dazu muss die Datenbank im „Einzelbenutzermodus“ gestartet werden:

  • SQL Server Configuration manager („SQL Server 2014-Konfigurations-Manager“) öffnen
  • Links im Baum unter den „SQL Server-Diensten“ rechts den SQL Server auswählen
  • Eigenschaften > Startparameter > „-m“ hinzufügen („Add“), ohne Anfürungszeichen
  • Dienst neu starten (nun ist die DB im Einzelbenutzermodus)
  • Mit SQLCMD zur Instanz verbinden:
C:\> "%ProgramFiles%\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn\SQLCMD.EXE" -S .\<INSTANZNAME>
  • Am SQL Prompt dann den Admin hinzufügen
1> EXEC sp_addsrvrolemember '<SERVER/DOMAINNAME>\<BENUTZER>', 'sysadmin'
2> GO
1> exit
  • Dann den Startparameter „-m“ wieder entfernen, den Dienst neu starten und an der Instanz mit dem gerade hinzugefügten Konto anmelden.

Fertig 🙂

Windows Server 2016 RDS Effekte (Black Screen, Startmenü defekt)

Problem:

Ein Terminal Server (RDS Session Host) zeigt nach einiger Zeit verschiedene Effekte, wie z.B. „schwarzer Bildschirm nach der Anmeldung“, „nicht mehr funktionierendes Startmenü“, allgemeine Performance- oder Anmeldeprobleme.

Dies betrifft übrigens nicht zwingend nur RDS-SHs, sondern prinzipiell alle Windows Server 2016 Maschinen, auf Terminalservern (insbesondere mit User Profile Disks, UPDs) ist das ganze aufgrund potenziell größerer Anmelde-/Benutzeranzahl nur deutlich wahrscheinlicher anzutreffen.

Lösung:

Schuld könnte ein Bug sein, welcher dafür sorgt, dass bei der Benutzeranmeldung erstellte Firewall-Regeln beim löschen des Benutzerprofils (hier kommen die UPDs ins spiel, unter Einsatz dieser wird das Profil nämlich bei der Abmeldung automatisch wieder vom Server gelöscht) nicht mehr entfernt werden.

Das verursacht einen Registry-Bloat in 

HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules

und/oder

HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System

Sind diese Keys bereits „überfüllt“, kann es gut sein, dass sich die Werte nicht mehr per GUI (regedit) entfernen lassen – der Key lädt schlichtweg ewigkeiten. Abhilfe schafft folgendes PowerShell-Script:

$profiles = get-wmiobject -class win32_userprofile
Clear-Host
Write-Host "`n`n`n`n`n`n`n`n"
Write-Host "Getting Firewall Rules..."
$Rules1 = Get-NetFirewallRule -All | 
  Where-Object {$profiles.sid -notcontains $_.owner -and $_.owner }
$Rules1Count = $Rules1.count
Write-Host "" $Rules1Count "Rules`n"

Write-Host "Getting Firewall Rules from ConfigurableServiceStore..."
$Rules2 = Get-NetFirewallRule -All -PolicyStore ConfigurableServiceStore | 
  Where-Object { $profiles.sid -notcontains $_.owner -and $_.owner }
$Rules2Count = $Rules2.count
Write-Host "" $Rules2Count "Rules`n"

$Total = $Rules1.count + $Rules2.count
Write-Host "Deleting" $Total "Firewall Rules:" -ForegroundColor Green

$Result = Measure-Command {

  $start = (Get-Date)
  $i = 0.0

  foreach($rule1 in $Rules1){

    # action
    Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules" -Name $rule1.name

    # progress
    $i = $i + 1.0
    $prct = $i / $total * 100.0
    $elapsed = (Get-Date) - $start
    $totaltime = ($elapsed.TotalSeconds) / ($prct / 100.0)
    $remain = $totaltime - $elapsed.TotalSeconds
    $eta = (Get-Date).AddSeconds($remain)

    # display
    $prctnice = [math]::round($prct,2) 
    $elapsednice = $([string]::Format("{0:d2}:{1:d2}:{2:d2}", $elapsed.hours, $elapsed.minutes, $elapsed.seconds))
    $speed = $i/$elapsed.totalminutes
    $speednice = [math]::round($speed,2) 
    Write-Progress -Activity "Deleting Rules ETA $eta elapsed $elapsednice loops/min $speednice" -Status "$prctnice" -PercentComplete $prct -SecondsRemaining $remain
  }

  foreach($rule2 in $Rules2) {

    # action  
    Remove-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System" -Name $rule2.name

    # progress
    $i = $i + 1.0
    $prct = $i / $total * 100.0
    $elapsed = (Get-Date) - $start
    $totaltime = ($elapsed.TotalSeconds) / ($prct / 100.0)
    $remain = $totaltime - $elapsed.TotalSeconds
    $eta = (Get-Date).AddSeconds($remain)

    # display
    $prctnice = [math]::round($prct,2) 
    $elapsednice = $([string]::Format("{0:d2}:{1:d2}:{2:d2}", $elapsed.hours, $elapsed.minutes, $elapsed.seconds))
    $speed = $i/$elapsed.totalminutes
    $speednice = [math]::round($speed,2) 
    Write-Progress -Activity "Deleting Rules from ConfugurableServiceStore ETA $eta elapsed $elapsednice loops/min $speednice" -Status "$prctnice" -PercentComplete $prct -secondsremaining $remain
  }
}

$end = Get-Date
Write-Host end $end 
Write-Host eta $eta

Write-Host $result.minutes min $result.seconds sec

Achtung: bei einem bereits länger laufenden Terminalserver, kann das Script schonmal so ein paar Stunden brauchen um alle Regeln zu entfernen. (In unserem Fall knapp 4 Stunden für etwa 95000 Regeln.)

Aus Performancegründen löscht das Script die Registry-Werte direkt, anstatt das Remove-NetFirewallRule Cmdlet zu verwenden.

Quelle: https://social.technet.microsoft.com/Forums/en-US/8dad5b1e-8236-4792-85fe-8725d74bbbcb/start-menu-not-coming-up-server-2016-rds?forum=winserverTS