2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

#01_FHEMWEB.pm: stricter check for websocket & auto SSL cert (Forum #108536)

git-svn-id: https://svn.fhem.de/fhem/trunk@21230 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2020-02-19 16:59:03 +00:00
parent da29770f71
commit 307dac0a35
4 changed files with 58 additions and 17 deletions

View File

@ -137,7 +137,7 @@ MQTT2_SERVER_Attr(@)
my ($type, $devName, $attrName, @param) = @_;
my $hash = $defs{$devName};
if($type eq "set" && $attrName eq "SSL") {
TcpServer_SetSSL($hash);
InternalTimer(1, "TcpServer_SetSSL", $hash, 0); # Wait for sslCertPrefix
}
return undef;
}
@ -660,7 +660,7 @@ MQTT2_SERVER_ReadDebug($$)
<a name="SSL"></a>
<li>SSL<br>
Enable SSL (i.e. TLS)
Enable SSL (i.e. TLS).
</li><br>
<li>sslVersion<br>

View File

@ -522,7 +522,9 @@ FW_Read($$)
"&fwcsrf=".$defs{$FW_wname}{CSRFTOKEN} : "");
if($FW_use{sha} && $method eq 'GET' &&
$FW_httpheader{Connection} && $FW_httpheader{Connection} =~ /Upgrade/i) {
$FW_httpheader{Connection} && $FW_httpheader{Connection} =~ /Upgrade/i &&
$FW_httpheader{Upgrade} && $FW_httpheader{Upgrade} =~ /websocket/i &&
$FW_httpheader{'Sec-WebSocket-Key'}) {
my $shastr = Digest::SHA::sha1_base64($FW_httpheader{'Sec-WebSocket-Key'}.
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
@ -2699,7 +2701,7 @@ FW_Attr(@)
my $retMsg;
if($type eq "set" && $attrName eq "HTTPS" && $param[0]) {
TcpServer_SetSSL($hash);
InternalTimer(1, "TcpServer_SetSSL", $hash, 0); # Wait for sslCertPrefix
}
if($type eq "set") { # Converting styles
@ -3844,8 +3846,12 @@ FW_show($$)
<ul>
mkdir certs<br>
cd certs<br>
openssl req -new -x509 -nodes -out server-cert.pem -days 3650 -keyout server-key.pem
openssl req -new -x509 -nodes -out server-cert.pem -days 3650
-keyout server-key.pem
</ul>
These commands are automatically executed if there is no certificate.
Because of this automatic execution, the attribute sslCertPrefix should
be set, if necessary, before this attribute.
<br>
</li>
@ -4585,7 +4591,9 @@ FW_show($$)
openssl req -new -x509 -nodes -out server-cert.pem -days 3650 -keyout
server-key.pem
</ul>
Diese Befehle werden beim Setzen des Attributes automatisch
ausgef&uuml;rht, falls kein Zertifikat gefunden wurde. Deswegen, falls
n&ouml;tig, sslCertPrefix vorher setzen.
<br>
</li>

View File

@ -317,11 +317,14 @@ telnet_Attr(@)
my $hash = $defs{$devName};
if($type eq "set" && $attrName eq "SSL") {
TcpServer_SetSSL($hash);
if($hash->{CD}) {
my $ret = IO::Socket::SSL->start_SSL($hash->{CD});
Log3 $devName, 1, "$hash->{NAME} start_SSL: $ret" if($ret);
}
InternalTimer(1, sub($) { # Wait for sslCertPrefix
my ($hash) = @_;
TcpServer_SetSSL($hash);
if($hash->{CD}) {
my $ret = IO::Socket::SSL->start_SSL($hash->{CD});
Log3 $devName, 1, "$hash->{NAME} start_SSL: $ret" if($ret);
}
}, $hash, 0); # Wait for sslCertPrefix
}
if(($attrName eq "allowedCommands" ||

View File

@ -131,10 +131,15 @@ TcpServer_Accept($$)
$err = "" if(!$err);
$err .= " ".($SSL_ERROR ? $SSL_ERROR : IO::Socket::SSL::errstr());
my $errLevel = ($err =~ m/error:14094416:SSL/ ? 5 : 1); # 61511
Log3 $name, $errLevel, "$type SSL/HTTPS error: $err (peer: $caddr)"
if($err !~ m/error:00000000:lib.0.:func.0.:reason.0./); #Forum 56364
close($clientinfo[0]);
return undef;
if($err =~ m/http request/) { # HTTP on HTTPS.
Log3 $name, $errLevel, "HTTP connect to HTTP socket (peer: $caddr)";
} else {
Log3 $name, $errLevel, "$type SSL/HTTPS error: $err (peer: $caddr)"
if($err !~ m/error:00000000:lib.0.:func.0.:reason.0./); #Forum 56364
close($clientinfo[0]);
return undef;
}
}
}
@ -170,9 +175,34 @@ TcpServer_SetSSL($)
if($@) {
Log3 $hash, 1, $@;
Log3 $hash, 1, "Can't load IO::Socket::SSL, falling back to HTTP";
} else {
$hash->{SSL} = 1;
return;
}
my $name = $hash->{NAME};
my $cp = AttrVal($name, "sslCertPrefix", "certs/server-");
if(! -r "${cp}key.pem") {
Log 1, "$name: Server certificate missing, trying to create one";
if($cp =~ m,^(.*)/(.*?), && ! -d $1 && !mkdir($1)) {
Log 1, "$name: failed to create $1: $!, falling back to HTTP";
return;
}
if(!open(FH,">certreq.txt")) {
Log 1, "$name: failed to create certreq.txt: $!, falling back to HTTP";
return;
}
print FH "[ req ]\nprompt = no\ndistinguished_name = dn\n\n".
"[ dn ]\nC = DE\nO = FHEM\nCN = home.localhost\n\n";
close(FH);
my $cmd = "openssl req -new -x509 -days 3650 -nodes -newkey rsa:2048 ".
"-config certreq.txt -out ${cp}cert.pm -keyout ${cp}key.pem";
Log 1, "Executing $cmd";
`$cmd`;
unlink("certreq.txt");
}
$hash->{SSL} = 1;
}