New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Securing connections with SSL not working on Solaris 10 x86 #246
Comments
So is the problem limited to a Solaris Also, if you are debugging the SSL handshake, I'm wondering if |
HI Charles, Thanks for your response. I haven’t had time yet to test/research some of your questions. I haven’t tried connecting to a Solaris upsmon to a RHEL upsd. We are not interested in doing that but I will try it for your troubleshooting benefit. I can tell you Solaris upsc also fails to connect to Solaris upsmon. It fails in the same way, with a failed ssl handshake. Once again upsd fails to recognize its an ssl connection and throws its fails to send back a server hello and its certificate. The openssl version on my RHEL system is 1.0.1e. It is the latest ssl package provided by Red Hat ( or was a couple months ago). On the solaris side we have 1.01.f. I hope to get back to you on Tuesday with more info. Would love to figure this out. We are a defense contractor and this is an security item that our client want us to fix. (trimmed) |
Understood that it is not the deliverable configuration, but it is a good consistency check. A quicker test is to just run the RHEL upsc against the Solaris upsd - no extra configuration needed. Solaris upsc to RHEL upsd might also shed some light on the SSL handshake issue. For future reference, this is how cURL handles things: https://github.com/bagder/curl/blob/master/lib/vtls/openssl.c#L1670
Thanks for confirming that.
Is NSS/NSPR a viable alternative to OpenSSL in your application? A bit of background: NUT has had OpenSSL-based SSL support in the source code for years, but due to some licensing complications https://people.gnome.org/~markmc/openssl-and-the-gpl.html, it didn't make it into many packaging systems. Eventually, NSS-based SSL support was added as an option, and that's what goes into the Debian/Ubuntu packages (and probably others). The OpenSSL code in NUT still compiles, but it was written for a much older version of OpenSSL, and it is not exercised often. (I am not a lawyer; views are my own and not necessarily my employer's; etc.) |
Sorry about the delay. I’m the usual almost overwhelmed systems engineer. With certificates enabled, I ran a Solaris upsc against a RHEL upsd. I did not receive a handshake failure. Rather it said connected with ssl. I then ran a RHEL upsc against a Solaris upsd and received the usual ssl handshake failure. Once again, the handshake blows up right away. The server receives the hello and throws an error. It never sends a hello or the certificate back. I recompiled 2.7.3 with the change you suggested in netssl.c. Change TLSv1 to TLSv2 in:
This failed to compile. It wasn’t able to identify the function TLSv2_server_method.
I am wondering if NUT is linking to the older ssl system libraries that are present on my system. Openssl 1.0.1p is installed in /usr/local/ssl. As you can see that path is what is referenced in the failing libtool command. Yet when I perform on ldd on successfully compiled upsd, I get
I’m expecting references to /usr/local/ssl not usr/lib. At every turn, I’ve taken care to specify the ssl path as /usr/local/ssl. I have the following ssl packages on my system. I’m hesitant to remove the system ones.
If this is the issue, I don’t know who to fix it. My configure command uses the ssl flags to tell it where to find it (as evidenced above). My PKG_CONFIG_PATH has /usr/local/ssl first. I do note that the nss package is installed on our working RHEL server. Whereas nss is not installed on the Solaris side. Our IA guy, says that installing nss is not an acceptable solution. (trimmed) |
Thanks, this is a good sanity check on the client side of the Solaris SSL library.
Not quite "TLSv2": TLSv1_2_server_method() The name "TLSv1_2" comes from "TLS v1.2", but it is munged into a C-compatible namespace.
It's been a while since I used the Solaris compiler/linker, but I think that the "-L" flags are parsed left-to-right (assuming they don't need to be split up into multiple -L arguments: "-L/usr/local/ssl/lib -L/usr/sfw/lib") so it might be searching /usr/sfw/lib first. |
https://en.wikipedia.org/wiki/OpenSSL says that TLSv1.2 was introduced in 1.0.1, so if the /usr/sfw/lib version is older, that makes sense. You might not even need to change the |
Thanks. I did figure out how to re-order the Linking directories as you can see below. Unfortunately the compile still fails in the same way.
This surprised me since it is suppose to be finding the newer version of openssl. I haven’t been able to locate any mechanism for it secretly looking elsewhere for header files and libraries. I have also noticed that the upsd binary looks specifically for libcrypto.so.0.9.7 and libssl.so.0.9.7. Whereas the newer variants are in libcrypto.a and libssl.a located in /usr/local/ssl/lib. But it doesn’t want these. I have noticed it is not trying the /usr/local/ssl/lib path. This path is not getting hard coded into upsd. I have tried everything from environment variables to C flags to change this but with no luck. But I don’t think that is relevant at this point because its specifically wanting libcrypto.so.0.9.7.
So its clear that my upsd is using the 0.9.7 version of ssl. If this is the case, why is it failing if its meant to work with older versions of openssl? I was wondering if the problem was that it was including header files from 1.0.1p and then trying to work with 0.9.7. So I stripped out every reference of /usr/local/ssl/lib from every flag and environment variable. I then installed my package with my certs. Sadly the upsc and upmon connections still failed. So this appears to not work with ssl 0.9.7 which would rule out the problem being with ssl being newer. Remember these are the very cert files and config file settings that succeed with my linux package. (trimmed) |
Something is still putting /usr/sfw/lib first in RUNPATH/RPATH, though.
The problem is that while there is a window of OpenSSL versions where we can expect that things would work (i.e. NUT uses TLS v1.0 support, which apparently hasn't been deprecated in OpenSSL yet - but NUT's SSL code predates the introduction of TLS v1.2), that doesn't mean that it will automatically work once those conditions are satisfied. I'm willing to believe that there is a bug in NUT's OpenSSL implementation (see also #202), but it works in Linux, so I suspect a subtle difference in Solaris system call semantics (or possibly in the versions you are linking against - but I think we are close to pinning that down). At this point, some more runtime log information would be helpful. I think you sent some client-side information: what about on the server side? Can you sanitize some of the packet captures? |
Here is the debug output from Solaris upsd when a connection is attempted by (.150) upsmon ./upsd -DD25.954192 write: [destfd=6] [len=12] [OK STARTTLS] Debug output from upsmon trying to connect to upsd (.121) ./upsmon -DDNetwork UPS Tools upsmon 2.7.3 Attached are the 6 packets generated by upsmon’s attempt to connect with upsd. The packet sniffer on Solaris 10 is snoop which is a variant of tcpdump. The proper way to read the output is to save to a file and then read that file with the snoop program. I have outputted the payload of each packet to the attached txt and docx file. All the data (header and payload) are contained in the binary file. The file can be read in wireshark or if you have access to snoop or tcpdump. The snoop command is “snoop –i binary-version –x0” to read the payloads. Snoop –i binary-version –V – for headers. Question: When my Linux upsmon is able to connect locally to upsd, why does it say Certificate Verification is Disabled? 0.003453 Trying to connect to UPS [power0@localhost] As an additional help I’ve included the tcpdump file for the successful linux connection. Its upsmon connecting to upsd over 127.0.0.1:3493. Its called Linux-success. I can see the certificate being passed over. And my password no longer being visible. Tcpdump file can be viewed in wireshark. One final note: My Solaris upsmon is now failing to connect to the Linux upsd. However it gets a bit farther in the handshake. ./upsmon –D0.014075 Trying to connect to UPS [power0@159.62.74.88] ./upsd -D9.214212 SSL_accept do not accept handshake.: Success (trimmed) 1 0.00000 192.168.72.150 -> JRE-SVR10168 TCP D=3493 S=42979 Syn Seq=1048990410 Len=0 Win=14600 Options=<mss 1460,sackOK,tstamp 2517451091 0,nop,wscale 7>
2 0.00030 192.168.72.150 -> JRE-SVR10168 TCP D=3493 S=42979 Ack=1553768145 Seq=1048990411 Len=0 Win=115 Options=<nop,nop,tstamp 2517451091 500688583>
3 0.00000 192.168.72.150 -> JRE-SVR10168 TCP D=3493 S=42979 Push Ack=1553768145 Seq=1048990411 Len=9 Win=115 Options=<nop,nop,tstamp 2517451091 500688583>
4 0.00050 192.168.72.150 -> JRE-SVR10168 TCP D=3493 S=42979 Ack=1553768157 Seq=1048990420 Len=0 Win=115 Options=<nop,nop,tstamp 2517451092 500688584>
5 0.00016 192.168.72.150 -> JRE-SVR10168 TCP D=3493 S=42979 Push Ack=1553768157 Seq=1048990420 Len=155 Win=115 Options=<nop,nop,tstamp 2517451092 500688584>
6 0.00044 192.168.72.150 -> JRE-SVR10168 TCP D=3493 S=42979 Fin Ack=1553768158 Seq=1048990575 Len=0 Win=115 Options=<nop,nop,tstamp 2517451093 500688584>
|
Attached is truss output for upsd. I ran a upsc power0@localhost and captured how upsd reacted. Other than seeing STARTTLS in there, it doesn’t mean much to me. |
Ah, this does look like issue #202 What confuses me is that the code should not get that error there - the file descriptor comes from select(), so it should be ready to read. (I think a short read is a different error code.) I will try to look at this over the holidays.
This might not be necessary, but note that none of your attachments are getting through to Github, only the text of your reply: #246 (comment)
https://github.com/networkupstools/nut/blob/master/clients/upsclient.c#L1041 and search for CERTVERIFY here: http://www.networkupstools.org/docs/man/upsmon.conf.html |
@tmcneill30 please try this patch: f098486 @aquette does the Ubuntu QA test cover SSL? Can you please run it with this patch to make sure I didn't break anything? The SSL_accept fix mostly targets the OpenSSL side, but there is one case for a zero-length read. |
Thanks for the patch. However it doesn’t compile. The problem is a change you made in upsd.c, namely, upsdebugx(2, "write: [destfd=%d] [len=%d] [%s]", client->sock_fd, len, str_rtrim(ans, '\n')); This line generates a symbol not found error. Did you mean str_trim? I say this because I don’t get any google hits for str_rtrim, but I do for str_trim. The str_rtrim function call doesn’t exist in the original version of upsd.c. Tom (trimmed) |
Compilation attempts with str_trim and strtrim also fail. I’m not a C developer hence I’m just guessing with these function names. (trimmed) |
I don't see that particular line in the patch. Are you grabbing the whole source tree from that revision? (I was thinking that you might want to minimize the number of lines changed from the base 2.7.3 version - the patch should be standalone, although I haven't tried that yet.) If you are using the whole Git source tree at f098486, you might need to re-run autogen.sh and configure, since a few files have been added since then (in particular, common/str.c has str_rtrim() and company). |
Confirmed that it builds on OS X. If you download this, you can apply it to a 2.7.3 tree with "patch -p1 < f098486.diff": https://github.com/networkupstools/nut/commit/f098486803921b8899d4172fff97846428d82c12.diff |
@clepple : sadly no, the Ubuntu QA test (also available in Debian) doesn't cover SSL yet. Part of the planned things for when NSS would be compiled in (already the case since 2.7.1-1) |
I had copied the entire files for netssl.c and upsd.c from github. I am not using git but rather the source tar for version 2.7.3. My brain lock for plugging in files from HEAD. Thanks for solving that for me. Now that I have patched the 2.7.3 files instead, the compile succeeds. Unfortunately the ssl connection is still broken. Here is what the debug output was: -bash-3.2# ./upsmon -D bash-3.2# ./upsd -D (trimmed) |
Is the CA certificate (and any intermediates, if applicable) included in CERTFILE? |
Yes. I created the certificates following the instructions listed in section 9.5 of the NUT documentation. Keep in mind that moving the exact same certificate files to my rhel server, I see no errors in debug mode and I confirmed thru packet sniffing that the connection between a local uspmon and upsd was indeed encrypted. I rechecked my config files for my Solaris test and upsmon.conf and upsd.conf have the proper settings. (trimmed) |
I wonder if the "unknown ca" is really an expired certificate. At one point you mentioned that Solaris upsmon couldn't connect to the RHEL upsd. I don't know when the validity checks occur in OpenSSL. (The NUT instructions do mention that the default command lines will create certificates that expire in 30 days.) (Also, when you reply by email, please trim off the previous text. GitHub apparently does not remove that automatically.) |
Good catch on the expired certificates but sadly after thorough re-testing I’m still getting the same message -bash-3.2# ./upsmon –D My retest consisted of: In summary, Solaris upsmon fails with above tracing, RHEL works fine with exact same certs. |
My mistake, it's the same blocking/non-blocking error on the client side. This commit should be added on top of the previous one: 213ee3d However, I can't really test that here: OS X does not have the non-blocking issue on the client side. It is no worse with this patch, though. |
I added your upsclient.c patch to my build. Verified patch succeeded. Re-made package and re-installed. I still get the below tracing when upsmon wants to connect locally with upsd. -bash-3.2# ./upsmon -D |
You might need to check with the OpenSSL developers, or a Solaris-specific forum. |
Hi, |
René, thanks for posting this, but isn't this patch is for the server listening socket? With the commits mentioned earlier in this issue, I think we have the server's client FD retrying. (Note that since the server is single-threaded, it shouldn't block - but the client API was written with the expectation that calls will block.) Were you able to reproduce the error in upsmon or upsc? |
f098486.patch.txt Pardon the .txt appended to each filename. Its my first time using github and it says it won't accept .tar or anything linux. For some reason it refused the zip file I made even though that is supposed to be acceptable. (file size limitation?) the zip was only 8.5 MB. Anyways, I"ve included the 2 patch files I made. One with your patch and the other from Clepple. I included my patched source (just to have you double check that my source was properly patched). I also included my package that was derived from that. (I have a build script that creates the package). My NUT compile relies on my openssl package which installs in /usr/local/ssl. That package is included. Again here is the configure command I used. Note lack of --with-wrap. then the usual make && make install The package includes the certificates and config files I am using. (If I get this working, I'll re-make my certificate) It also installs /etc/init.d/ups_nut.init. I haven't taken the time yet to move it from legacy to SMF. Thank you for looking at these. Let me if you need anything further. |
There is a problem with your compilation options, your binaries are not linked with your OpenSSL but with the system (and old) openssl located in /usr/sfw/lib The SSL connexions work but the server certificate check fails. In upsmon.conf if you set CERTVERIFY 0 everything works fine. I'm still investigating to understand why the certificate check fails. You are using a self-signed certificate for your server. I tried with a root CA and a server cert and it fails too using your binaries. It works with my binaries but I'm not using /usr/sfw openssl libs. Next step : I will recompile your wineries with your sources and your options but I will ensure that your OpenSSL is used. |
I think this is tangential to the SSL issue, but note that in ./configure option parsing, the lack of an option allows the script to auto-detect the library or feature. You might want |
SSL test results for nut-2.7.3 and patch f098486 on solaris 10 (32 or 64 bits)
I guess that upsc can never check server certificates because it has no configuration file to make it search for trusted certificate authorities. libwrap disturbs server certificate check but it still allows SSL connections. Tests realized with OpenSSL 1.0.1q, 1.0.2e and the one in solaris directory /usr/sfw (0.9.7d) |
Is libwrap altering the linker flags? |
You are right. --with-wrap changes the library path order at compile time and thus it always links with the libssl located in /usr/sfw/lib I managed to use configure options to make it use the libraries I want and now everything works (except server certificate verify with upsc as this is only available with nss, not openssl) So. tmcneil30, to compile and openssl to match your needs : export LD_RUN_PATH=/usr/local/ups/lib:/usr/local/ssl/lib:/usr/sfw/lib The to compile NUT with f098486 patch included : You can remove LD_LIBRARY_PATH stuff in your init script, as it will no longer be needed thanks to LD_RUN_PATH set at compile time. ldd /usr/local/ups/sbin/upsmon Using solaris libssl in /usr/srw/lib makes upsmon fail in certificate verify when compiling with libwrap |
Rene - thank you for figuring this out. Especially for compiling --with-wrap. That is a requirement for me. I haven't had time to test your instructions, but will soon and will report back my results. question - are the patches still necessary? |
Yes upsd patch f098486 is needed to establish incoming ssl connections.
I didn't mention that I've been using gcc to compile under Solaris.
|
I've followed your instructions and .... SUCCESS!! However I needed to apply not only the f09486 patch but the patch you sent me was well. If you haven't done so, I would commit that patch and post the number here. I was still getting ssl errors in upsd until I recompiled with your patch. The LD_RUN_PATH was critical to getting the ups binaries to depend upon my newer ssl. I did need to re-compile ssl as you stated above. Last question - do I hit the close button? How do I know the 2 patches will make it into the next version of NUT? |
My usual procedure is to close the issue when all of the patches are merged into master. At this point, that branch is slated to be the basis for the next release. However, unless I missed an update, the O_NDELAY removal patch has the potential for a denial-of-service if someone only partially completes the SSL handshake. |
I did not apply the O_NDELAY removal patch. The f09486 patch against nut-2.7.3 was enough to make SSL work fine under Solaris. Please check again because it should work with only one of those patches, both are not needed. |
I re-checked and still get the same results. I start upsd -D and initially get this: I then start upsmon: Once upsmon connects, I get the following from upsd When I add in the O_NDELAY patch, the SSL errors do not appear. |
I have tested your attached packages and I am running into the same error messages as you (SSL_ERROR_WANT_READ). What gcc compiler are you using ? I am using my self compiled gcc 4.8.3 gcc -vUsing built-in specs. |
-bash-3.2$ gcc -v |
I switched my c compiler to a newer one I had installed. Same result. Still get ssl errors from upsd upon a upsmon connection. -bash-3.2$ gcc -v Attached is my config.log. I don't use --prefix because I don't want 'make install' to install in /usr/local/ups. I instruct make install directly to install in a build directory. And then of course I am creating a package from there. Other than that, I believer our configure commands are the same, but maybe you can spot something in there. |
I've just tried the same compiler as you (gcc 3.4.3 from /usr/sfw/bin) and I'm not getting the SSL error. |
My solaris: Also I am running in 32 bit mode. Its a requirement I have for this. |
OpenSSL is ok. My nut with your OpenSSL works fine. The problem seems to be in nut only. Please can you send me your source code in a tar file. I want to compare files. |
certainly. |
Oh! When comparing sources I have just realized that I am using a source tree where O_NDELAY is already removed! That’s why everything was working fine from the beginning. If I set O_NDELAY (or O_NONBLOCK) I have the SSL_ERROR_WANT_READ message. BUT! According to patched source code this is only a warning message. Return code is 0 from the ssl_error() function. upsmon is connected to upsd using SSL with CERTVERIFY. Communication works OK I have tested the configuration using dummy-ups driver to simulate power0 UPS. Everything looks ok I can see 3 consecutive SSL_ERROR_WANT_READ per STARTTLS connection startup. 3 first ones to your power0 UPS. 3 next to your ups0 UPS that is missing from ups.conf. So I suggest to keep O_NDELAY set and to ignore the SSL_ERROR_WANT_READ message as it is only an harmless debug message. If you prefer to remove O_NDELAY to prevent those ugly debug messages you no longer need patch f098486. Note : in your /etc/init.d/ups_nut.init script path to upsdrvctl is wrong, should be /sbin/ instead of /bin/ (2 lines) |
If I remove the f098486 patch, I am back to having ssl handshake failures. Keep in mind, I am using the released 2.7.3 source. I re-tested just now to be sure. I was thinking that perhaps the change in compilation options for NUT and SSL were enough to fix this problem. But no, without the f098486 patch, the ssl handshake fails. I'd prefer not to have ugly debug warnings but that is preferable to a DOS vulnerability. So I'm not sure what should be done with that patch going forward, but it is necessary to secure NUT running Solaris. When I get time, I'll packet sniff the upsd/upsmon connection and verify the connection is truly functional. Will report back then. |
packet sniffing confirms that communication from upsmon to upsd is encrypted despite debug ssl warnings from upsd. So I finally have something that works even though its not entirely pretty. |
We can raise the debug level of the SSL_ERROR_WANT_READ. However, they are not logged to syslog, just to the console in debug mode. Other than that, it sounds like we're good to merge f098486 and its corresponding client-side patch, 213ee3d. If either of you have suggestions for how we can change the documentation, let me know. The user manual is in Asciidoc, which is mostly plain text, but I don't mind reformatting if you tell me what to include, and where. |
FYI - I tested with 213ee3d and still got the upsd debug ssl warnings. For my edification, why do I need 213ee3d. The documentation seems fine to me. I don't know if there is a place for a caveat that if you are running on Solaris you can't use the standard ssl libraries if you want to encrypt connections. |
My thought was that if the server-side sockets default to non-blocking, the client-side sockets need to be forced back to blocking because the non-SSL API doesn't provide a way to just loop back around the way that the select() loop does on the server side. It's one of those "if you don't need it now, you probably will later" correctness patches. Might depend on the size of the various packets over the TCP connection.
Sometimes we interpret "FAQ" as "Frequently Anticipated Questions"... When you say "standard SSL libraries" do you mean SFW? |
Ø Sometimes we interpret "FAQ" as "Frequently Anticipated Questions"... When you say "standard SSL libraries" do you mean SFW? Yes I did mean /usr/sfw From: Charles Lepple [mailto:notifications@github.com] My thought was that if the server-side sockets default to non-blocking, the client-side sockets need to be forced back to blocking because the non-SSL API doesn't provide a way to just loop back around the way that the select() loop does on the server side. It's one of those "if you don't need it now, you probably will later" correctness patches. Might depend on the size of the various packets over the TCP connection.
Sometimes we interpret "FAQ" as "Frequently Anticipated Questions"... When you say "standard SSL libraries" do you mean SFW? — |
Cheers all, noticed this discussion and that a fix was proposed here (branch https://github.com/networkupstools/nut/compare/ssl_accept_nbio still exists) but not merged into main NUT codebase. Any memories - what did this stall on? Did the change solve the practical issue? |
I have compiled versions 2.6.5, 2.7.1 & 2.7.3 and have been unable to implement ssl encryption between upsd and the other processes such as upsmon etc on Solaris 10.
My target machine and build server are running Solaris 10/08 running in 32 bit mode. Both servers are recently patched. All other nut functionality is working fine on target server. I am compiling with gcc, gmake, etc.
My configure command is:
Configure reports that all ssl libraries are found. /usr/local/ssl contains a build of openssl 1.0.1p. My openssl was used to create the certificate and works well with other packages I have on the system such as ntp and ssh.
I have followed the instructions in the documentation in section 9.5 "Configuring SSL". I created upsd.pem and a certificate using instructions in documentation.
I changed the following configuration entries
I also compiled and made a 2.7.3 and 2.7.1 nut package for RHEL 6. When I change above config settings and use the exact same cert and key, the upsmon to upsd connection is encrypted!! I verified this thru packet sniffing and upmon itself now states it is using ssl. So I know my Solaris problem is not with the certficate files nor with my understanding of how to configure NUT.
ldd on upsd on rhel6 and solaris both list ssl shared objects as dependencies.
upsmon and upsd debugging show that upsmon says hello and upsd does not understand the hello. It should say hello back and then send its certificate. This occurs on RHEL6 but the ssl handshake fails immediately on Solaris 10/08.
Open config.txt in wordpad or vi. This is config.log.
The text was updated successfully, but these errors were encountered: