Archiv der Kategorie: Software

Alles was mit Software zu tun hat

Debian Jessie: linux-base Fehler bei Installation neuer Backport-Kernel

Debian mag stabil sein, der aktuell bei Jessie mitgelieferte 3.16er Kernel wird von einigen Dingen jedoch nicht mehr unterstützt, die Installation dieser Softwarepakete ist also nicht mehr möglich. Glücklicherweise gibt es die so genannten Backports, welche neuere Versionen bereitstellen. Nicht ganz so gut getestet, aber immerhin eine Möglichkeit.

Die Einrichtung geht recht schnell – man muss lediglich folgende Zeile in /etc/apt/sources.list hinzufügen:

deb http://ftp.debian.org/debian jessie-backports main

Sucht man nun nach linux-image, also dem Kernel, findet man auch einige neue Versionen. In meinem Fall ist die 4.9.0 aktuell:

# apt-cache search linux-image
...
linux-image-4.9.0-0.bpo.1-amd64
...

Leider gelingt die Installation nicht ohne Klimmzüge, denn der erste Versuch wird mit einer Fehlermeldung quittiert:

# apt-get install linux-image-4.9.0-0.bpo.1-amd64 linux-headers-4.9.0-0.bpo.1-amd64
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
Einige Pakete konnten nicht installiert werden. Das kann bedeuten, dass
Sie eine unmögliche Situation angefordert haben oder, wenn Sie die
Unstable-Distribution verwenden, dass einige erforderliche Pakete noch
nicht erstellt wurden oder Incoming noch nicht verlassen haben.
Die folgenden Informationen helfen Ihnen vielleicht, die Situation zu lösen:

Die folgenden Pakete haben unerfüllte Abhängigkeiten:
linux-image-4.9.0-0.bpo.1-amd64 : Hängt ab von: linux-base (>= 4.3~) aber 3.5 soll installiert werden
Empfiehlt: firmware-linux-free soll aber nicht installiert werden
Empfiehlt: irqbalance soll aber nicht installiert werden
E: Probleme können nicht korrigiert werden, Sie haben zurückgehaltene defekte Pakete.

Auf den ersten Blick scheint es jedoch keine neue Verison des Paketes zu geben:

linux-base is already the newest version.

Ursache ist die Priorisierung: Sowohl im „offiziellen“ Jessie-Repository als auch in den Backports steckt ein Paket mit dem Namen linux-base. Zwar ist jenes in den Backports aktueller, jedoch werden die Pakete des Stable-Repos bevorzugt. Abhilfe schafft es das Paket explizit aus dem Backports-Repo zu beziehen.

apt-get -t jessie-backports install linux-base

Im Anschluss ist auch die Installation des Kernels fehlerfrei möglich. Mit dieser Methode kann man auch das Kernel-Metapaket installieren um zukünftige Updates automatisch zu erhalten:

apt-get -t jessie-backports install linux-image-amd64

ZFS/ZOL: Pool UNAVAIL nach Reboot

Nicht schön. Nach dem Reboot eines Server musste ich feststellen, dass diverse Storages nicht mehr zugreifbar waren. Schnell stellte sich heraus, dass alle ZFS-Pools offline waren und die Geräte mit der Meldung „too many errors“ als FAULTED markiert wurden.

 zpool import
   pool: tempstore
     id: xyz
  state: UNAVAIL
 status: One or more devices are faulted.
 action: The pool cannot be imported due to damaged devices or data.
 config:

        tempstore   UNAVAIL  insufficient replicas
          sdd       FAULTED  too many errors
          sde       FAULTED  too many errors

   pool: storage
     id: xyy
  state: UNAVAIL
 status: One or more devices are faulted.
 action: The pool cannot be imported due to damaged devices or data.
 config:

        storage     UNAVAIL  insufficient replicas
          sdb       FAULTED  too many errors

Nunja, Consumer-Platten traue ich ja viele defekte zu, aber drei unabhängige Platten gleichzeitig? Eher nein. Auch S.M.A.R.T. zeigte keine wirklich bedenkenswerten Werte. Aufschlussreicher ist da schon das Kernel-Log:

[  776.890127] Large kmem_alloc(131128, 0x1000), please file an issue at:
               https://github.com/zfsonlinux/zfs/issues/new
[  776.890129] CPU: 1 PID: 12969 Comm: vdev_open Tainted: P           O    4.4.39-gentoo-adlerweb #2
[  776.890130] Hardware name: LENOVO yxz/        , BIOS xyz 01/10/2012
[  776.890132]  0000000000000000 ffff880417a37bc0 ffffffff813545d8 000000000240c200
[  776.890134]  0000000000000000 ffff880417a37c00 ffffffffa0018af1 0000000017a37be0
[  776.890138]  0000000000000000 ffff88041626d480 ffff8804174ed660 0000000000004000
[  776.890139] Call Trace:
[  776.890144]  [<ffffffff813545d8>] dump_stack+0x4d/0x65
[  776.890148]  [<ffffffffa0018af1>] spl_kmem_zalloc+0x131/0x180 [spl]
[  776.890163]  [<ffffffffa0109aa8>] vdev_cache_stat_fini+0x258/0xcc0 [zfs]
[  776.890175]  [<ffffffffa010a3ba>] vdev_cache_stat_fini+0xb6a/0xcc0 [zfs]
[  776.890188]  [<ffffffffa014426a>] zio_data_buf_free+0x51a/0xdc0 [zfs]
[  776.890200]  [<ffffffffa014798f>] zio_nowait+0xaf/0x190 [zfs]
[  776.890215]  [<ffffffffa0104cce>] vdev_probe+0xfe/0x200 [zfs]
[  776.890228]  [<ffffffffa01059e0>] ? vdev_accessible+0x70/0x2b0 [zfs]
[  776.890240]  [<ffffffffa0107969>] vdev_open+0x3c9/0x4b0 [zfs]
[  776.890251]  [<ffffffffa0107bdd>] vdev_open_children+0x18d/0x1c0 [zfs]
[  776.890254]  [<ffffffffa001b8ec>] taskq_dispatch+0x3ac/0x5b0 [spl]
[  776.890257]  [<ffffffff810c1ed0>] ? wake_up_q+0x70/0x70
[  776.890261]  [<ffffffffa001b6e0>] ? taskq_dispatch+0x1a0/0x5b0 [spl]
[  776.890263]  [<ffffffff810b8c04>] kthread+0xc4/0xe0
[  776.890265]  [<ffffffff810b8b40>] ? kthread_park+0x50/0x50
[  776.890268]  [<ffffffff81a6a5df>] ret_from_fork+0x3f/0x70
[  776.890270]  [<ffffffff810b8b40>] ? kthread_park+0x50/0x50

*kick* Da war ja was. ZOL läuft wegen der Lizenzproblematik als Kernel-Modul. Ich hatte zuletzt am Kernel einige Treiber nachgezogen. Hierbei sind zwar Version und Ablageort gleich geblieben, offenbar ist aber die ABI etwas gewandert, sodass SPL/ZFS etwas verwirrt den Dienst quittierten.

Für Gentoo heißt das einmal Module neu Bauen, in meinem Fall

emerge -va spl zfs-kmod

 

Alternativ und in den meisten Fällen zuverlässiger ist es nach jeder Kernel-Änderung alle Module automatisch neu zu erstellen:

emerge -va @module-rebuild

Storage online, Admins glücklich, Update-Doku ergänzt. Passt.

vSphere vCenter Server Appliance (vCSA) 6.0 -> 6.5 VIX Upgrade Fehler

Beim Upgrade einer vCSA 6.0 zu 6.5 ergeben sich die tollsten Fehlermeldungen – und keine ist dokumentiert. Immerhin eine konnte ich Dank des VMWare-Forums schnell herausfinden:

"A problem occurred while getting data from the source vCenter Server."

Selbstverständlich waren die Zugangsdaten des Quellserver korrekt und funktionierten in WebUI bzw. SSH fehlerfrei. Ich übersetze mal in eine für Administratoren verständliche Sprache:

"Kennwort abgelaufen"

Nachdem ein neues Kennwort vergeben wurde läuft das Update an dieser Stelle weiter.

Nutzung von GIT auf Debian/Ubuntu nicht möglich: GnuTLS

(Anm: Angeblich soll der Bug inzwischen behoben sein)

Debian und dessen Devirate geben sich zur Zeit wieder eine Menge Mühe meine Vorurteile zu erfüllen. Dieses mal hat es GIT erwischt: Beim Klonen eines Repositories kommt es zu einem Verbindungsfehler durch GnuTLS.


2$ git clone https://github.com/freifunk-gluon/gluon.git gluon -b v2016.2.2
Klone nach 'gluon' ...
fatal: unable to access 'https://github.com/freifunk-gluon/gluon.git/': gnutls_handshake() failed: Public key signature verification has failed.

Offenbar hat die bei Debian mitgelieferte Version von GnuTLS Probleme mit einigen Cipher-Suites und Proxyservern. Ich folge mal den Tipps von Nyambaa@AskUbuntu bzw. xmendez und habe GIT statt mit GnuTLS gegen OpenSSL gebaut:

apt-get update
apt-get install build-essential fakeroot dpkg-dev libcurl4-openssl-dev
apt-get build-dep git
mkdir /usr/src/git/
cd /usr/src/git
apt-get source git
dpkg-source -x git_2.1.4-2.1+deb8u2.dsc
cd git-2.1.4

Die Version muss natürlich der jeweils aktuellen angepasst werden – lässt sich ggf. per ls nach apt-get source herausfinden.

In der Datei debian/control muss nun überall der Text libcurl4-gnutls-dev gegen libcurl4-openssl-dev ersetzt werden. Im Anschluss wird das Paket gebaut und installiert. Ggf meckert buildpackage noch über fehlende libraries, welche man schnell per apt-get nachziehen kann.

dpkg-buildpackage -rfakeroot -b
dpkg -i git_2.11.0+next.20161205-1_amd64.deb git-man_2.11.0+next.20161205-1_all.deb

Nun sollte das installierte git auf OpenSSL basieren und keine Verbindungsprobleme mehr zeigen.

VMWare vMotion auf VMA per CLI auslösen

Kleines Script zwischendurch: Über dieses Perl-Konstrukt kann man auf einem vSphere Management Assistant eine vMotion auf der Konsole auslösen. So lassen sich recht einfach eventgesteuerte vMotion-Aktionen umsetzen. Ich nutze es z.B. um zeitgesteuert VMs an Standorte mit höherer erwarteter Hitrate zu verlegen oder bei Störungen kritische VMs automatisiert auf „sicherere“ Hosts zu migrieren. Das Original stammt von William Lam, ich habe einige Punkte etwas umgebaut um Storage-vMotion auszuklammern. Üblicher Disclaimer: Proof of concept, keine Garantie, nicht-Programmierer-versucht-sich-an Perl, Works for me.

#!/usr/bin/perl -w

# Reworked for standard vmotion: Florian Knodt - https://www.adlerweb.info

# Original for distinct storage: William Lam - http://blogs.vmware.com/vsphere/automation

use strict;

use warnings;

use VMware::VILib;

use VMware::VIRuntime;

use Data::Dumper;

my %opts = (

    vmname => {

        type => "=s",

          help => "Name of Virtual Machine to migrate",

        required => 1,

    },

    vihost => {

          type => "=s",

          help => "Name of ESXi host to migrate to",

          required => 1,

     },

    priority => {

        type => "=s",

          help => "Migration priority [high|low]",

          required => 0,

        default => 'high',

    },

);

Opts::add_options(%opts);

Opts::parse();

Opts::validate();

Util::connect();

my $vmname = Opts::get_option('vmname');

my $vihost = Opts::get_option('vihost');

my $priority = Opts::get_option('priority');

if(Vim::get_service_content()->about->apiVersion lt "5.1") {

    &seeya("Script requires vCenter Server >5.1\n");

}

# define priority enums

my %priorityConstants = ('high' => 'highPriority', 'low' => 'lowPriority');

# retrieve VM

my $vm_view = Vim::find_entity_view(view_type => 'VirtualMachine', filter => {'name' => $vmname}, properties => ['name']);

if(!defined($vm_view)) {

    &seeya("Unable to find VM: " . $vmname . "\n")

}

# retrieve host

my $host_view = Vim::find_entity_view(view_type => 'HostSystem', filter => {'name' => $vihost}, properties => ['name']);

if(!defined($host_view)) {

    my $test = Vim::find_entity_view(view_type => 'HostSystem', properties => ['name']);

    print Dumper($test);

    &seeya("Unable to find ESXi host: " . $vihost . "\n");

}

# in case bad input

if($priority ne "low" || $priority ne "high") {

    $priority = "high";

}

$priority .= "Priority";

my ($task,$message);

eval {

    # call migrate API

    print "Migrating " . $vmname . " to ESXi Host: " . $vihost . "...\n";

    $task = $vm_view->MigrateVM_Task(host => $host_view, priority => VirtualMachineMovePriority->new($priority));

    $message = "Successfully migrated " . $vmname . "!\n";

    &getStatus($task,$message);

};

if($@) {

    print "Error: " . $@ . "\n";

}

Util::disconnect();

sub getStatus {

     my ($taskRef,$message) = @_;

     my $task_view = Vim::get_view(mo_ref => $taskRef);

     my $taskinfo = $task_view->info->state->val;

     my $continue = 1;

     while ($continue) {

        my $info = $task_view->info;

        if ($info->state->val eq 'success') {

                print $message,"\n";

                return $info->result;

                $continue = 0;

        } elsif ($info->state->val eq 'error') {

                my $soap_fault = SoapFault->new;

                $soap_fault->name($info->error->fault);

                $soap_fault->detail($info->error->fault);

                $soap_fault->fault_string($info->error->localizedMessage);

                die "$soap_fault\n";

        }

        sleep 5;

        $task_view->ViewBase::update_view_data();

     }

}

sub seeya {

    my ($message) = @_;

    print $message;

    Util::disconnect();

    exit 1;

}

Aufruf:

./scriptname.pl --server vcenter.domain.local --username admin --password admin --vmname MyVM --vihost esxihost2.domain.local

STDOUT verdoppeln mit ftee

Mal wieder eine etwas andere Anforderung: Für eine automatische Verarbeitung soll eine Audioquelle durch eine Software auf der Konsole ausgewertet werden. Die Software ist hierbei für die Analyse von Dateien ausgelegt, kann allerdings auch von STDIN lesen. So weit kein Problem – arecord kümmert sich um die Aufnahme und per STDOUT/Pipe geht es in die Analysesoftware. Leider gibt es hier einen Haken: Es funktioniert nicht zuverlässig. Um zu prüfen ob die Audioquelle oder die Analyse das Problem verursacht müsste ich die eingehenden Audiodateien abhören. Am PC ginge das mit Pulseaudio recht einfach, am Server möchte ich auf dieses Ressourcen- und Dependency-Monster jedoch vorzugsweise verzichten.

Dann halt per File

Meine erste Idee: tee. Mit diesem Befehl kann man die Dateien einer Pipe in eine zusätzliche Datei „abzwacken“:

arecord hw:1,0 | tee test.daten | analyzer -

Was prinzipiell funktioniert hat jedoch einen entscheidenden Nachteil: Es landet alles in der Datei. Dauerhaft. Möchte man nicht, dass die Festplatte voll läuft, muss man nach dem reinhören das Konstrukt abbrechen und ohne tee-Befehl neu starten. Eher unschön, denn das heißt auch Deattime, also eine kurze Zeitspanne in der ich möglicherweise Ereignisse verpasse.

Und was ist mit FIFO?

Als Alternative eignet sich ein FIFO, auch als named Pipe bezeichnet. Diese lassen sich mit mkfifo anlegen und stellen sozusagen einen „Puffer“ zur Verfügung, über den sich Prozesse verbinden lassen. Hier können wir im ersten Terminal z.B. wie folgt starten:

mkfifo test.fifo
arecord hw:1,0 | tee test.fifo | analyzer -

und im Zweiten den Stream abgreifen

cat test.fifo > test.daten

Dummerweise gibt es auch hier Probleme: Es blockiert. Der Analyzer im ersten Terminal wird erst gestartet, wenn wir im Zweiten beginnen den Puffer zu lesen. Schlimmer noch: Brechen wir im zweiten Terminal das Mitlesen ab wird auch der Analyzer beendet. Nicht wirklich was ich suche.

Dauer-Interimslösung

Nunja, da mir die Ideen ausgingen und das Internet auf den ersten Blick nichts passendes lieferte blieb es erst mal bei der dauerhaften Dateiaufzeichnung auf einen speziell limitierten Ordner. Lief alle paar Wochen die zugehörige Partition voll brach die Software ab und ich startete per Hand neu. Auf der Todo-Liste stand etwas von automatischen Neustarts oder einem Gebastel um nur bei Bedarf die Ausgabe zur named Pipe zu starten. Dieser Zustand hielt nun für etwa 2 Jahre.

Rettung bei Stackoverflow

Heute ging es dann um die Behebung. Ich hatte grade ein Rendering gestartet und entsprechend etwas Leerlauf als die altbekannte Mail kam: Partition voll, die Erkennung steht. Jetzt reicht es. Also schnell auf Google und etwas in die Verwendung von Named Pipes einlesen.

Moment.

Nach kurzer Recherche landete ich bei Stackoverflow (wo auch sonst). Nach „Linux non-blocking fifo“ erkundigt sich der Autor „Dronus“ und beschreibt ein Szenario, welches recht Nah an meine Andorderungen heran kam. Und Beantworter „racic“ lieferte auf ganzer Linie: „ftee“ nennt sich sein überschaubarer C-Code, welcher das verhalten von tee nachmacht, jedoch für den FIFO nicht blockiert. Auch wird SIGPIPE, welches beim Abbrechen des Lesevorgangs der Pipe ausgelöst wird, nicht beachtet, der Analyzer läuft also fleißig weiter. Greift man später erneut auf die Pipe zu erhält man wieder die aktuellen Daten.

Wer „wichtige“ Daten nutzt kann alternativ auf das ebenfalls dort zu findende bftee von Fabraxias zurückgreifen, welches bei einem Abbruch der Verbindung alle eingehenden Daten zwischenspeichert und bei der nächsten Verbindung erst einmal nachliefert.

Für mich ist die nicht gepufferte Variante ideal – alte Audiodaten sind für mich nicht relevant. Das Kompilieren ist mit aktuellem GCC schnell erledigt und allein das ersetzen von tee gegen ftee im vorherigen Beispiel löst alle Probleme. Der Analyzer läuft und ich kann bei Bedarf in den Audiostream reinhören ohne eine Unterbrechung der Auswertung zu bekommen. Fein.

FRITZ!Box per Konsole auslesen (PHP/TR64)

Statistiken sind toll. Wäre fein, wenn man auch der FRITZ!Box einiges entlocken könnte. Das Zauberwort lautet TR64 und ist über HTTP/SOAP im LAN erreichbar. Hierzu müssen in den Netzwerkeinstellungen die Anwendungszugriffe und Statusinformationen aktiv sein.

Bild: https://www.adlerweb.info/blog/wp-content/uploads/2017/01/fbox-300×137.png

Allgemeine Infos wie die aktuell verwendete Bandbreite lassen sich von jedem Abrufen, andere Bereiche konnte ich bisher nur über /control abrufen – hier werden die Zugangsdaten eines FB-Nutzers benötigt.

Über das Protokoll lassen sich neben IP, Verbindungsstatus und Bandbreiten auch erweiterte Infos wie Dämpfungen & Co aufzeichnen. Technisch kann man sogar Aktionen wie einen Reconnect oder komplette Konfigurationsänderungen durchführen, das würde hier jedoch den Rahmen sprengen. Einige Infos gibt es in der Wiki von WeHaveMoreFun oder das ausgiebigere Perl-Modul von FHem.

Hier mal mein Notizzettel, welcher eine Abfrage per PHP erlaubt:

<?php



function FbSOAP($url, $urn, $method='GetInfo', $user='', $pass='') {
    $parameter = array(
        'location'   => $url,
        'uri'        => $urn,
        'noroot'     => True
    );

    if($user != '') $parameter['login'] = $user;
    if($pass != '') $parameter['password'] = $pass;

    $client = new SoapClient(
        null,
        $parameter
    );
    $status = $client->$method();
    return $status;
}

$host = 'http://fritz.box:49000';
$user = 'nutzer';
$pass = 'geheim';

//Aktuell verwendete Bandbreite, Traffic seit Boot, DNS-Konfiguration (kein Passwort nötig)
var_dump(FbSOAP($host.'/igdupnp/control/WANCommonIFC1', 'urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1', 'GetAddonInfos'));

/*
  ["NewByteSendRate"]=>
  string(5) "20709"
  ["NewByteReceiveRate"]=>
  string(5) "21372"
  ["NewPacketSendRate"]=>
  string(1) "0"
  ["NewPacketReceiveRate"]=>
  string(1) "0"
  ["NewTotalBytesSent"]=>
  string(9) "986828869"
  ["NewTotalBytesReceived"]=>
  string(10) "1140825575"
  ["NewAutoDisconnectTime"]=>
  string(1) "0"
  ["NewIdleDisconnectTime"]=>
  string(2) "30"
  ["NewDNSServer1"]=>
  string(14) "217.237.15.1"
  ["NewDNSServer2"]=>
  string(14) "217.237.14.2"
  ["NewVoipDNSServer1"]=>
  string(14) "217.237.15.1"
  ["NewVoipDNSServer2"]=>
  string(14) "217.237.14.2"
  ["NewUpnpControlEnabled"]=>
  string(1) "0"
  ["NewRoutedBridgedModeBoth"]=>
  string(1) "1"
*/

//Verbindungsstatus und Typ (kein Passwort nötig)
var_dump(FbSOAP($host.'/igdupnp/control/WANCommonIFC1', 'urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1', 'GetCommonLinkProperties'));

/*
Achtung - MaxBitRate ist nicht konsistent

array(4) {
  ["NewWANAccessType"]=>
  string(3) "DSL"
  ["NewLayer1UpstreamMaxBitRate"]=>
  string(7) "1073000"
  ["NewLayer1DownstreamMaxBitRate"]=>
  string(7) "2304000"
  ["NewPhysicalLinkStatus"]=>
  string(2) "Up"
}
*/

//DSL-Sync-Status, DSL-Datenraten und Dämpfungen
var_dump(FbSOAP($host.'/upnp/control/wandslifconfig1', 'urn:dslforum-org:service:WANDSLInterfaceConfig:1', 'GetInfo', $user, $pass));

/*
array(15) {
  ["NewEnable"]=>
  string(1) "1"
  ["NewStatus"]=>
  string(2) "Up"
  ["NewDataPath"]=>
  string(11) "Interleaved"
  ["NewUpstreamCurrRate"]=>
  string(3) "224"
  ["NewDownstreamCurrRate"]=>
  string(4) "2304"
  ["NewUpstreamMaxRate"]=>
  string(4) "1196"
  ["NewDownstreamMaxRate"]=>
  string(4) "4736"
  ["NewUpstreamNoiseMargin"]=>
  string(3) "270"
  ["NewDownstreamNoiseMargin"]=>
  string(3) "130"
  ["NewUpstreamAttenuation"]=>
  string(3) "290"
  ["NewDownstreamAttenuation"]=>
  string(3) "490"
  ["NewATURVendor"]=>
  string(8) "41564d00"
  ["NewATURCountry"]=>
  string(4) "0400"
  ["NewUpstreamPower"]=>
  string(3) "502"
  ["NewDownstreamPower"]=>
  string(3) "500"
}
*/

//DSL-Fehlerstatistiken
var_dump(FbSOAP($host.'/upnp/control/wandslifconfig1', 'urn:dslforum-org:service:WANDSLInterfaceConfig:1', 'GetStatisticsTotal', $user, $pass));

/*
array(15) {
  ["NewReceiveBlocks"]=>
  string(1) "0"
  ["NewTransmitBlocks"]=>
  string(1) "0"
  ["NewCellDelin"]=>
  string(1) "0"
  ["NewLinkRetrain"]=>
  string(1) "9"
  ["NewInitErrors"]=>
  string(1) "0"
  ["NewInitTimeouts"]=>
  string(1) "0"
  ["NewLossOfFraming"]=>
  string(1) "0"
  ["NewErroredSecs"]=>
  string(3) "637"
  ["NewSeverelyErroredSecs"]=>
  string(2) "54"
  ["NewFECErrors"]=>
  string(7) "3932348"
  ["NewATUCFECErrors"]=>
  string(1) "9"
  ["NewHECErrors"]=>
  string(4) "7289"
  ["NewATUCHECErrors"]=>
  string(2) "10"
  ["NewCRCErrors"]=>
  string(4) "1635"
  ["NewATUCCRCErrors"]=>
  string(2) "13"
}
*/

//Gerätemodell, Softwareversion, Seriennummer, Logfile
var_dump(FbSOAP($host.'/upnp/control/deviceinfo', 'urn:dslforum-org:service:DeviceInfo:1', 'GetInfo', $user, $pass));

/*
array(12) {
  ["NewManufacturerName"]=>
  string(3) "AVM"
  ["NewManufacturerOUI"]=>
  string(6) "00040E"
  ["NewModelName"]=>
  string(28) "FRITZ!Box Fon WLAN 7390 (UI)"
  ["NewDescription"]=>
  string(37) "FRITZ!Box Fon WLAN 7390 (UI) 84.06.51"
  ["NewProductClass"]=>
  string(9) "FRITZ!Box"
  ["NewSerialNumber"]=>
  string(12) "C02506210000"
  ["NewSoftwareVersion"]=>
  string(8) "84.06.51"
  ["NewHardwareVersion"]=>
  string(28) "FRITZ!Box Fon WLAN 7390 (UI)"
  ["NewSpecVersion"]=>
  string(3) "1.0"
  ["NewProvisioningCode"]=>
  string(0) ""
  ["NewUpTime"]=>
  string(7) "2375523"
  ["NewDeviceLog"]=>
  string(15974) "03.01.17 02:32:46 Internetverbindung wurde erfolgreich hergestellt. IP-Adresse: xxxx, DNS-Server: 217.237.150.xx und 217.237.148.xx, Gateway: 87.186.225.xx, Breitband-PoP: xxx05-asr
03.01.17 02:32:46 Internetverbindung wurde getrennt.
03.01.17 02:32:43 Die Internetverbindung wird kurz unterbrochen, um der Zwangstrennung durch den Anbieter zuvorzukommen.
…
*/

//Software-Update verfügbar?
var_dump(FbSOAP($host.'/upnp/control/userif', 'urn:dslforum-org:service:UserInterface:1', 'GetInfo', $user, $pass));
/*
array(9) {
  ["NewUpgradeAvailable"]=>
  string(1) "0"
  ["NewPasswordRequired"]=>
  string(1) "0"
  ["NewPasswordUserSelectable"]=>
  string(1) "1"
  ["NewWarrantyDate"]=>
  string(19) "0001-01-01T00:00:00"
  ["NewX_AVM-DE_Version"]=>
  string(0) ""
  ["NewX_AVM-DE_DownloadURL"]=>
  string(0) ""
  ["NewX_AVM-DE_InfoURL"]=>
  string(0) ""
  ["NewX_AVM-DE_UpdateState"]=>
  string(8) "NoUpdate"
  ["NewX_AVM-DE_LaborVersion"]=>
  string(0) ""
}
*/

//WLAN-Konfiguration und Status
var_dump(FbSOAP($host.'/upnp/control/wlanconfig1', 'urn:dslforum-org:service:WLANConfiguration:1', 'GetInfo', $user, $pass));

/*
array(17) {
  ["NewEnable"]=>
  string(1) "0"
  ["NewStatus"]=>
  string(8) "Disabled"
  ["NewMaxBitRate"]=>
  string(4) "Auto"
  ["NewChannel"]=>
  string(2) "13"
  ["NewSSID"]=>
  string(17) "ADLERWEB-TEST"
  ["NewBeaconType"]=>
  string(3) "11i"
  ["NewMACAddressControlEnabled"]=>
  string(1) "0"
  ["NewStandard"]=>
  string(1) "n"
  ["NewBSSID"]=>
  string(17) "C0:25:06:00:00:00"
  ["NewBasicEncryptionModes"]=>
  string(4) "None"
  ["NewBasicAuthenticationMode"]=>
  string(4) "None"
  ["NewMaxCharsSSID"]=>
  string(2) "32"
  ["NewMinCharsSSID"]=>
  string(1) "1"
  ["NewAllowedCharsSSID"]=>
  string(95) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
  ["NewMinCharsPSK"]=>
  string(2) "64"
  ["NewMaxCharsPSK"]=>
  string(2) "64"
  ["NewAllowedCharsPSK"]=>
  string(22) "0123456789ABCDEFabcdef"
}
*/

//DSL-Status und Konfiguration
var_dump(FbSOAP($host.'/upnp/control/wandsllinkconfig1', 'urn:dslforum-org:service:WANDSLLinkConfig:1', 'GetInfo', $user, $pass));

/*
array(9) {
  ["NewEnable"]=>
  string(1) "1"
  ["NewLinkStatus"]=>
  string(2) "Up"
  ["NewLinkType"]=>
  string(5) "PPPoE"
  ["NewDestinationAddress"]=>
  string(9) "PVC: 1/32"
  ["NewATMEncapsulation"]=>
  string(3) "LLC"
  ["NewAutoConfig"]=>
  string(1) "0"
  ["NewATMQoS"]=>
  string(3) "UBR"
  ["NewATMPeakCellRate"]=>
  string(1) "0"
  ["NewATMSustainableCellRate"]=>
  string(1) "0"
}
*/

//DSL-Statistiken
var_dump(FbSOAP($host.'/upnp/control/wandsllinkconfig1', 'urn:dslforum-org:service:WANDSLLinkConfig:1', 'GetStatistics', $user, $pass));

/*
array(4) {
  ["NewATMTransmittedBlocks"]=>
  string(1) "0"
  ["NewATMReceivedBlocks"]=>
  string(1) "0"
  ["NewAAL5CRCErrors"]=>
  string(1) "0"
  ["NewATMCRCErrors"]=>
  string(1) "0"
}
*/

//PPP-Status (incl. externer IP!)
var_dump(FbSOAP($host.'/upnp/control/wanpppconn1', 'urn:dslforum-org:service:WANPPPConnection:1', 'GetInfo', $user, $pass));

/*
BitRate auch hier nicht nachvollziehbar

array(31) {
  ["NewEnable"]=>
  string(1) "1"
  ["NewConnectionStatus"]=>
  string(9) "Connected"
  ["NewPossibleConnectionTypes"]=>
  string(21) "IP_Routed, IP_Bridged"
  ["NewConnectionType"]=>
  string(9) "IP_Routed"
  ["NewName"]=>
  string(8) "internet"
 ["NewUptime"]=>
  string(5) "57428"
  ["NewUpstreamMaxBitRate"]=>
  string(7) "1083169"
  ["NewDownstreamMaxBitRate"]=>
  string(7) "4289207"
  ["NewLastConnectionError"]=>
  string(10) "ERROR_NONE"
  ["NewIdleDisconnectTime"]=>
  string(1) "0"
  ["NewRSIPAvailable"]=>
  string(1) "0"
  ["NewUserName"]=>
  string(40) "deineid@t-online.de"
  ["NewNATEnabled"]=>
  string(1) "1"
  ["NewExternalIPAddress"]=>
  string(13) "91.35.130.0"
  ["NewDNSServers"]=>
  string(30) "217.237.150.0, 217.237.148.0"
  ["NewMACAddress"]=>
  string(17) "C0:25:06:00:00:00"
  ["NewConnectionTrigger"]=>
  string(8) "AlwaysOn"
  ["NewLastAuthErrorInfo"]=>
  string(0) ""
  ["NewMaxCharsUsername"]=>
  string(3) "128"
  ["NewMinCharsUsername"]=>
  string(1) "3"
  ["NewAllowedCharsUsername"]=>
  string(87) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._@()#/%[]{}*+§$&=?!:;,"
  ["NewMaxCharsPassword"]=>
  string(2) "64"
  ["NewMinCharsPassword"]=>
  string(1) "3"
  ["NewAllowedCharsPassword"]=>
  string(87) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._@()#/%[]{}*+§$&=?!:;,"
  ["NewTransportType"]=>
  string(5) "PPPoE"
  ["NewRouteProtocolRx"]=>
  string(3) "Off"
  ["NewPPPoEServiceName"]=>
  string(0) ""
  ["NewRemoteIPAddress"]=>
  string(0) ""
  ["NewPPPoEACName"]=>
  string(10) "xxxx05-asr"
  ["NewDNSEnabled"]=>
  string(1) "1"
  ["NewDNSOverrideAllowed"]=>
  string(1) "1"
}

*/


?>

 

Amdroid/CM: Eingehende SMS werden nicht angezeigt

Die Älteren unter euch können sich eventuell erinnern: SMS. Ein System um Textnachrichten an Mobiltelefone zu senden. Begrenzte Textlänge, hohe Gebühren und nicht verschlüsselt. Eigentlich heute Obsolet, aber einige Anbieter denken immer noch, dass dieses Verfahren modern sei – auch wenn es seit fast 7 Jahren als unsicher eingestuft wird. Hallo Banken. Es kam wie es kommen musste: Ich sah mich genötigt ein Produkt über eine dieser Gesellschaften zu bezahlen und – nichts. Während die Webseite freudig vermeldete, dass ich eine passende TAN erhalten hätte machte mein Handy keinen Mucks. Toll, ich hab ein Zahlungsziel. Aber auch nichts ungewöhnliches – im Telefonica-Netz kommt es ja nicht unbedingt selten zu Störungen, also warten wir halt.

Einige Stunden später noch immer nichts, also müssen wir wohl selbst Hand anlegen. Erste Anlaufstelle: Test-SMS senden. Gar nicht so einfach, denn SMS-Funktion hab ich eigentlich auf keinem anderen Gerät mehr installiert. Glücklicherweise habe ich noch einen „echten“ Telefonanschluss ohne VoIP und konnte daher per Modem ein SMS-Gateway erreichen. Allerdings ohne Erfolg. Also machen wir mal ein altes Handy fit und versuchen es da – woho, SMS. Es muss also an meinem Endgerät liegen.

Per ADB zeigt sich nach einigem (teuren) Geteste folgender Fehler:

12-14 11:07:05.216  3179  5307 W MmsSmsDatabaseHelper: Upgrading database from version 64 to 67.
12-14 11:07:05.216  3179  5307 E SQLiteLog: (1) table sms_restricted already exists
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper: table sms_restricted already exists (code 1): , while compiling: CREATE VIEW sms_restricted AS SELECT * FROM sms WHERE type=1 OR type=2;
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper: android.database.sqlite.SQLiteException: table sms_restricted already exists (code 1): , while compiling: CREATE VIEW sms_restricted AS SELECT * FROM sms WHERE type=1 OR type=2;
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1677)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1608)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at com.android.providers.telephony.MmsSmsDatabaseHelper.upgradeDatabaseToVersion66(MmsSmsDatabaseHelper.java:1721)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at com.android.providers.telephony.MmsSmsDatabaseHelper.onUpgrade(MmsSmsDatabaseHelper.java:1466)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:256)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at com.android.providers.telephony.SmsProvider.query(SmsProvider.java:160)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.content.ContentProvider.query(ContentProvider.java:1020)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.content.ContentProvider$Transport.query(ContentProvider.java:239)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper:  at android.os.Binder.execTransact(Binder.java:565)
12-14 11:07:05.218  3179  5307 E MmsSmsDatabaseHelper: Destroying all old data.

Das kommt mir doch irgendwie bekannt vor… Schade, dass der Fehler nicht in der GUI erscheint und man so vermutet, dass alles ohne Störung funktionieren würde. Also löschen wir auch hier die kaputte Datenbank. Leider nicht ganz so einfach, denn zu dieser Meldung schweigen sich die Suchmaschinen aus und auch im Log wird der Dateiname der betroffenen Datenbank leider nicht erwähnt. Abhilfe schafft „Self Rubber Ducking“ , welcher augenscheinlich sehr von Migrationscode angetan ist. Fündig wurde ich dann im Ordner, welcher sich auch schon bei der Telefonie als Verursacher zeigte – hätte man drauf kommen können. Meh.

Also – leicht angepasst:

adb shell
su -
rm -rf /data/user_de/0/com.android.providers.telephony/databases/mmssms.*

Nach einem Reboot kann dann auch der Fintechler wieder mit mir kommunizieren. Ich wäre ja dafür langsam mal offene Standards für sowas zu schaffen – sowas wie U2F mit angezeigten Transaktionsdaten…

Amdroid/CM: com.android.phone force-close nach Update

Ja, schmutzig ist praktisch – zumindest wenn es um Updates geht. Obwohl die meisten Entwickler empfehlen möglichst bei jedem Update mit einem frischen System zu beginnen versuche ich meine Daten so lange wie möglich mitzuschleifen („Dirty Flash“) – leider gibt es noch immer unzählige Apps, welche keine brauchbare Backup-Funktion bieten und auch systembasierte Lösungen wie Titanium Backup sind leider nicht unfehlbar.

Zuletzt war ich etwas nachlässig – mein Handy war noch auf Version 2, aktuell Version 9 meiner aktuellen ROM. Zeit zum Aktalisieren, vor allem da Dirty Cow gerade bekannt wurde.

Also, Sideload drüber und – narf. „Telefon reagiert nicht mehr“. Gemeint ist hierbei die Telefon-App, also jene, welche Sprachtelefonie ermöglicht. Brauch ich zwar normal nicht, aber die Popups nerven doch etwas.

Über ADB ließ sich folgendes im Log erspähen:

12-06 16:43:32.820  3708  3708 E AndroidRuntime: FATAL EXCEPTION: main
12-06 16:43:32.820  3708  3708 E AndroidRuntime: Process: com.android.phone, PID: 3708
12-06 16:43:32.820  3708  3708 E AndroidRuntime: java.lang.IllegalArgumentException: column 'user_network_mode' does not exist
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:333)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at android.database.CursorWrapper.getColumnIndexOrThrow(CursorWrapper.java:87)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.telephony.SubscriptionController.getSubInfoRecord(SubscriptionController.java:293)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.telephony.SubscriptionController.getSubInfoUsingSlotIdWithCheck(SubscriptionController.java:1631)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.telephony.SubscriptionInfoUpdater.updateSubscriptionInfoByIccId(SubscriptionInfoUpdater.java:593)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.telephony.SubscriptionInfoUpdater.handleSimLoaded(SubscriptionInfoUpdater.java:421)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.telephony.SubscriptionInfoUpdater.handleMessage(SubscriptionInfoUpdater.java:338)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:102)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:154)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:6140)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
12-06 16:43:32.820  3708  3708 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)

Dankenswerterweise gibt es einen passenden Post von Daan, welcher die Ursache genau beschreibt und einen passenden Befehl zum zurücksetzen der defekten Datenbank anbietet. Hierbei gehen ggf. Einstellungen verloren, diese muss man ggf. später von seiner Datensicherung wieder einspielen.

adb shell
su -
rm -rf /data/user_de/0/com.android.providers.telephony/databases/telephony.*

Nach dem Befehl war dann Ruhe und sogar das telefonieren funktioniert wieder. Fein.

Windows/GPG/Smartcard – GPG mit Powershell bei SC-Verbindung neu starten

Beim Thema E-Mail-Verschlüsselung ist GPG weit verbreitet. Die Gundfunktionen sind z.B. mit Thunderbird und Enigmail oder gar eine Appliance auch für Einsteiger nutzbar und durch das WoT erstpart man sich die Abhängigkeit von – teils Zweifelhaften – zentralen Zertifizierungsstellen. Ich selbst nutze seit einiger Zeit keinen Softwareschlüssel sondern ein dediziertes HSM (Hardware Security Module) in Form eines YubiKey. Hiermit befindet sich der Key nicht mehr auf dem PC und auch die Verschlüsselung/Signierung läuft in Teilen auf dem Prozessor des YubiKey. Was unter Linux ohne große Änderungen funktioniert macht bei Windows eher wenig Spaß. Zwar ist auch GPG4Win in der Lage mit CryptoCards & Co umzugehen, häufiges Ein- und Ausstecken führt jedoch schnell zu einem hängenden GPG-Agent oder Absturzen der scdaemon.exe (GPG SmartCard Daemon). Einzige Abhilfe: Alle GPG-Prozesse beenden und neu starten. Da Verschlüsselung und Windows ohnehin eher selten zu finden ist sind auch Informationen dazu dünn gesät. Da ich teilweise um das System aus Redmond nicht herum komme und ein Fix in GPG4Win nicht in Sichtweite ist muss also wieder einmal der Holzhammer her: Irgendwie muss beim Einstecken des USB-Gerätes das GPG-System zurückgesetzt werden.

Also frisch ans Werk. Als Sprache soll mal wieder Powershell herhalten – direkt verfügbar, halbwegs systemnah, sollte passen. Über WMI kann man sich auch über ab- und angesteckte Geräte informieren lassen. Leider konnte ich keine Möglichkeit finden weitere Infos wie z.B. Hersteller oder Treiber gleich mit zu erhalten. Da sonst eher wenig Gerätefluktuation zu erwarten ist ziehe ich die „passt scho“-Karte und werde das GPG-System bei jedem neu auftauchenden Gerät einmal zurücksetzen.

#Requires -version 2.0
Register-WmiEvent -Class Win32_DeviceChangeEvent -SourceIdentifier deviceChange
write-host (get-date -format s) " Beginning script..."
do {
    $newEvent = Wait-Event -SourceIdentifier deviceChange
    $eventType = $newEvent.SourceEventArgs.NewEvent.EventType
    $eventTypeName = switch($eventType) {
        1 {"Configuration changed"}
        2 {"Device arrival"}
        3 {"Device removal"}
        4 {"docking"}
    }
    write-host (get-date -format s) " Event detected = " $eventTypeName

    $newEvent.SourceEventArgs.NewEvent | fl

    if ($eventType -eq 2) {
            write-host (get-date -format s) " Starting task in 3 seconds..."
            start-sleep -seconds 3
            taskkill /T /F /IM gpg-agent.exe
            taskkill /T /F /IM scdaemon.exe
            taskkill /T /F /IM kleopatra.exe

            start -FilePath 'C:\Program Files (x86)\GNU\GnuPG\gpg-agent.exe' -ArgumentList '--daemon' -WorkingDirectory 'C:\Program Files (x86)\GNU\GnuPG\' -LoadUserProfile -WindowStyle Minimized
    }
    Remove-Event -SourceIdentifier deviceChange
} while (1-eq1) #Loop until next event
Unregister-Event -SourceIdentifier deviceChange

Das Grundkonstrukt selbst scheint von Andy.L13 zu stammen, die kläglichen versuche von Mass-Storage auf andere USB-Geräte umzustellen stammen von mir. In Zeile 24 kann man für WindowStyle statt Minimized auch Hidden nutzen um das Ganze im Hintergrund laufen zu lassen – ich bevorzuge ein optisches Feedback. Das Script kann passend in Autostart oder als geplanter Task verstaut werden.

Sicher keine saubere Lösung, aber „works for me“.


Edit: Stackoverflow (bzw warriorpostman) liefert

Das folgende Script reagiert nur noch auf den vom YubiKey emulierten Smartcard-Reader. Das Objekt $Event.SourceEventArgs.NewEvent.TargetInstance sieht wie folgt aus – die Informationen für’s Query sollten sich im Gerätemanager finden lassen:

__GENUS                     : 2
__CLASS                     : Win32_PnPEntity
__SUPERCLASS                : CIM_LogicalDevice
__DYNASTY                   : CIM_ManagedSystemElement
__RELPATH                   : Win32_PnPEntity.DeviceID="USB\\VID_1050&PID_0116&MI_02\\6&***&0&0002"
__PROPERTY_COUNT            : 24
__DERIVATION                : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER                    : TESTRECHNER
__NAMESPACE                 : root\CIMV2
__PATH                      : \\TESTRECHNER\root\CIMV2:Win32_PnPEntity.DeviceID="USB\\VID_1050&PID_0116&MI_02\\6&***&0&0002"
Availability                : 
Caption                     : Microsoft Usbccid-Smartcard-Leser (WUDF)
ClassGuid                   : {50dd5230-ba8a-11d1-bf5d-0000f805f530}
CompatibleID                : {USB\Class_0b&SubClass_00&Prot_00, USB\Class_0b&SubClass_00, USB\Class_0b}
ConfigManagerErrorCode      : 0
ConfigManagerUserConfig     : False
CreationClassName           : Win32_PnPEntity
Description                 : Microsoft Usbccid-Smartcard-Leser (WUDF)
DeviceID                    : USB\VID_1050&PID_0116&MI_02\6&***&0&0002
ErrorCleared                : 
ErrorDescription            : 
HardwareID                  : {USB\VID_1050&PID_0116&REV_***&MI_02, USB\VID_1050&PID_0116&MI_02}
InstallDate                 : 
LastErrorCode               : 
Manufacturer                : Microsoft
Name                        : Microsoft Usbccid-Smartcard-Leser (WUDF)
PNPDeviceID                 : USB\VID_1050&PID_0116&MI_02\6&***&0&0002
PowerManagementCapabilities : 
PowerManagementSupported    : 
Service                     : WUDFRd
Status                      : OK
StatusInfo                  : 
SystemCreationClassName     : Win32_ComputerSystem
SystemName                  : TESTRECHNER
PSComputerName              : TESTRECHNER

Ich werde mich am Service WUDFRd (aka Gerät mit Windows SmartCard-Treber) orientieren. Prinzipiell könne man aber auch auf die USB-ID triggern uns so Scripte bauen, welche bei einstecken eines USB-Sticks ein Backup durchführen oder bei verbinden einer unbekannten USB-Tastatur entsprechend reagieren (böse Ente). Das zugehörige Script:

$query =  "Select * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity' AND TargetInstance.Service = 'WUDFRd'"

if( Get-EventSubscriber | Where-Object {$_.SourceIdentifier -eq "YubiHammer"}) {
    Unregister-Event YubiHammer
}

Register-WmiEvent -Query $query -SourceIdentifier YubiHammer -Action{
    $Global:RemoteProcMon=$event 

    start-sleep -seconds 3
    taskkill /T /F /IM gpg-agent.exe
    taskkill /T /F /IM scdaemon.exe
    taskkill /T /F /IM kleopatra.exe

    start -FilePath 'C:\Program Files (x86)\GNU\GnuPG\gpg-agent.exe' -ArgumentList '--daemon' -WorkingDirectory 'C:\Program Files (x86)\GNU\GnuPG\' -LoadUserProfile -WindowStyle Minimized
}