I am using NSS for a server application, a multi-threaded program
running on Linux. I have encountered a number of questions, and would be
glad to know if anyone has more information. My questions are based on
following the "Overview of an SSL Application" (
http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslintro.html).
1.
When writing an application that uses NSS, I would expect all Platform
Dependent configuration to reside in some configuration file, so that
the build process of the whole application will not need to be aware of
these details. However, the platform name and other properties appear
again and again in the Include path, the Library search path and in
command line defines, as you can see below - the command is copied from
running "make" in SSLsample, and contains many references to Linux,
Unix, x86 etc. Am I missing something here?
... -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall -pipe
-DHAVE_STRERROR -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE-DXP_UNIX
-DDEBUG -UNDEBUG -DDEBUG_yahel -D_REENTRANT
-I../../../../dist/Linux2.4_x86_glibc_PTH_DBG.OBJ/include
-I../../../../dist/public/nss -I../../../../dist/private/nss
Linux2.4_x86_glibc_PTH_DBG.OBJ/server.o
Linux2.4_x86_glibc_PTH_DBG.OBJ/sslsample.o
../../../../dist/Linux2.4_x86_glibc_PTH_DBG.OBJ/lib/libsectool.a
-Wl,-rpath,'$ORIGIN/../lib'
-Wl,-rpath-link,../../../../dist/Linux2.4_x86_glibc_PTH_DBG.OBJ/lib
-L../../../../dist/Linux2.4_x86_glibc_PTH_DBG.OBJ/lib -lssl3 -lsmime3
-lnss3 -L../../../../dist/Linux2.4_x86_glibc_PTH_DBG.OBJ/lib -lplc4
-lplds4 -lnspr4 -lpthread -ldl -lc
2.
How can I build using only static libraries?
3.
How should an application generate error strings? The examples at
SSLsample do a very strange trick. On the other hand, selfserv on my
machine simply finds no error string (for example, when using a bad
certificate database, error "-8174").
4.
It is explained that we can either configure a listen socket for SSL
using SSL_ConfigSecureServer(), or listen in the regular manner and then
configure enable SSL on the socket created by PR_Accept(). Is
SSL_ConfigSecureServer() just an elegant way to enable SSL on all
sockets created from some listen socket, and nothing else? Does it add
any security?
5.
Is there a simple example of an NSS client and server? I understand that
the SSLsample example are not considered good enough. However, selfserv
and strsclnt are rather complicated, since they handle numerous
configuration options.
6.
bug report - in function setupSSLSocket() of SSLsample/client.c, any
failure leads to closing tcpSocket, even after SSL_ImportFD(), which
replaces tcpSocket by sslSocket.
Thanks,
Yahel Zamir.
The scheme of naming built directories that way allows us to build NSS in
the same source tree on many platforms (via NFS or CIFS) simultaneously.
The builds and their results do not clash because they use separate
directories.
Is this a problem for you? You're not required to keep the files in the
directories where they are built, nor in directories with the same names
as where they are built.
> 2.
> How can I build using only static libraries?
You can't. For SOME of NSS's libraries, it is possible to link with the
.a instead of the .so. But that is not true of all the relevant libraries.
You really should use the shared libs. The symbols "exported" by those
shared libs are (mostly) the "public" symbols, the symbols that are
documented and intended for use by non-NSS code. If you use the .a files,
you are likely to use private symbols.
We do not guarantee backwards compatibility of private symbols. Private
symbols may change in any release. So you should stick with public ones.
> 3.
> How should an application generate error strings? The examples at
> SSLsample do a very strange trick. On the other hand, selfserv on my
> machine simply finds no error string (for example, when using a bad
> certificate database, error "-8174").
I suggest you look at SECU_PrintError for guidance. Sounds like you've
found another bug in SSLSample.
> 4.
> It is explained that we can either configure a listen socket for SSL
> using SSL_ConfigSecureServer(), or listen in the regular manner and then
> configure enable SSL on the socket created by PR_Accept().
EIther way, it is necessary to call SSL_ConfigSecureServer.
> Is SSL_ConfigSecureServer() just an elegant way to enable SSL on all
> sockets created from some listen socket, and nothing else? Does it add
> any security?
It is the sole means by which you configure the certificates and private
keys on the SSL server socket.
> 5.
> Is there a simple example of an NSS client and server? I understand that
> the SSLsample example are not considered good enough. However, selfserv
> and strsclnt are rather complicated, since they handle numerous
> configuration options.
SSLsample is the simplest example NSS has.
> 6.
> bug report - in function setupSSLSocket() of SSLsample/client.c, any
> failure leads to closing tcpSocket, even after SSL_ImportFD(), which
> replaces tcpSocket by sslSocket.
It's not a bug. You will find that the value returned by SSL_ImportFD
is the same as the value of "fd" (the second argument) passed to it.
>
> Thanks,
> Yahel Zamir.
--
Nelson B
We didn't write good stand-alone makefiles for SSLsample.
Instead, SSLsample's makefiles include common makefiles that
we use to build NSS itself. This is why you see a lot of
configuration macros on the compiler command line, that are
not really necessary for an application that uses NSS. Sorry
about the confusion.
To compile NSS, you just need to use the platform-dependent
flags for compiling a multithreaded application. This flag
is usually called -pthread or -pthreads on Unix platforms.
This requirement is actually for the NSPR library, which NSS
depends on.
As a reference, here are the flags we use to compile and link
an application that uses NSS on Linux:
$ nss-config --cflags
-I/usr/include/nss3
$ nss-config --libs
-Wl,-rpath-link,/usr/lib -L/usr/lib -lssl3 -lsmime3 -lnss3
You should replace /usr/include/nss3 and /usr/lib by the directories
where you installed the NSS headers and libraries.
Similarly the flags for an application that uses NSPR on Linux:
$ nspr-config --cflags
-I/usr/include/nspr4
$ nspr-config --libs
-L/usr/lib -lplds4 -lplc4 -lnspr4 -lpthread -ldl
> 2.
> How can I build using only static libraries?
This is no longer possible. You can get very close, by
imitating how we build the commands in mozilla/security/nss/cmd/xxx
where we set USE_STATIC_LIBS=1 in the manifest.mn file. But even
in that case, you still need the shared library libfreebl3.so, so
it's not 100% static libraries.
(On some Unix platforms we have multiple libfreebl_xxx_3.so's, one
for each version of the processor.)
Note that we discourage the use of NSS static libraries and don't
officially support it.
> 3.
> How should an application generate error strings? The examples at
> SSLsample do a very strange trick. On the other hand, selfserv on my
> machine simply finds no error string (for example, when using a bad
> certificate database, error "-8174").
I'm afraid that right now each application needs to build its own
NSS error string table. You can use the error string table for the
NSS command-line tools as an example:
http://lxr.mozilla.org/security/source/security/nss/cmd/lib/secerror.c
> 4.
> It is explained that we can either configure a listen socket for SSL
> using SSL_ConfigSecureServer(), or listen in the regular manner and then
> configure enable SSL on the socket created by PR_Accept(). Is
> SSL_ConfigSecureServer() just an elegant way to enable SSL on all
> sockets created from some listen socket, and nothing else? Does it add
> any security?
I'll let Nelson answer this question.
> 5.
> Is there a simple example of an NSS client and server? I understand that
> the SSLsample example are not considered good enough. However, selfserv
> and strsclnt are rather complicated, since they handle numerous
> configuration options.
Unfortunately no.
Anyone have a simple NSS client and server?
> 6.
> bug report - in function setupSSLSocket() of SSLsample/client.c, any
> failure leads to closing tcpSocket, even after SSL_ImportFD(), which
> replaces tcpSocket by sslSocket.
Thank you for the bug report. Would you have time to file it in
bugzilla.mozilla.org? If not, I can do it for you.
Wan-Teh
I just wanted add the existing bug reports on this issue:
https://bugzilla.mozilla.org/show_bug.cgi?id=66472
https://bugzilla.mozilla.org/show_bug.cgi?id=329017
Wan-Teh
Yes, it seems that an application does not need any specific library or
-D flag, except -pthread. I used just that, and my applications had no
trouble yet.
>> 2.
>> How can I build using only static libraries?
>
> This is no longer possible. You can get very close, by
> imitating how we build the commands in mozilla/security/nss/cmd/xxx
> where we set USE_STATIC_LIBS=1 in the manifest.mn file. But even
> in that case, you still need the shared library libfreebl3.so, so
> it's not 100% static libraries.
> (On some Unix platforms we have multiple libfreebl_xxx_3.so's, one
> for each version of the processor.)
> Note that we discourage the use of NSS static libraries and don't
> officially support it.
>
OK.
>> 3.
>> How should an application generate error strings? The examples at
>> SSLsample do a very strange trick. On the other hand, selfserv on my
>> machine simply finds no error string (for example, when using a bad
>> certificate database, error "-8174").
>
> I'm afraid that right now each application needs to build its own
> NSS error string table. You can use the error string table for the
> NSS command-line tools as an example:
>
> http://lxr.mozilla.org/security/source/security/nss/cmd/lib/secerror.c
>
I see. Actually, this is what SSLsample does.
>> 4.
>> It is explained that we can either configure a listen socket for SSL
>> using SSL_ConfigSecureServer(), or listen in the regular manner and
>> then configure enable SSL on the socket created by PR_Accept(). Is
>> SSL_ConfigSecureServer() just an elegant way to enable SSL on all
>> sockets created from some listen socket, and nothing else? Does it add
>> any security?
>
> I'll let Nelson answer this question.
>
OK
>> 5.
>> Is there a simple example of an NSS client and server? I understand
>> that the SSLsample example are not considered good enough. However,
>> selfserv and strsclnt are rather complicated, since they handle
>> numerous configuration options.
>
> Unfortunately no.
>
> Anyone have a simple NSS client and server?
>
I have written a simplistic client and server,
based on SSLsample and selfserv/strsclnt.
You are welcome to use it if you find it useful.
>> 6.
>> bug report - in function setupSSLSocket() of SSLsample/client.c, any
>> failure leads to closing tcpSocket, even after SSL_ImportFD(), which
>> replaces tcpSocket by sslSocket.
>
> Thank you for the bug report. Would you have time to file it in
> bugzilla.mozilla.org? If not, I can do it for you.
>
> Wan-Teh
>
I am not sure there is a bug here, since Nelson disagrees (see his message).
Yahel.
Essentially I have an existing build system, which I would like to keep
as simple as possible. Therefore I try to avoid any -D flags and so on.
Wan-Teh Chang has replied that these are excessive, so I'm fine now...
>> 2.
>> How can I build using only static libraries?
>
> You can't. For SOME of NSS's libraries, it is possible to link with the
> .a instead of the .so. But that is not true of all the relevant libraries.
>
> You really should use the shared libs. The symbols "exported" by those
> shared libs are (mostly) the "public" symbols, the symbols that are
> documented and intended for use by non-NSS code. If you use the .a files,
> you are likely to use private symbols.
>
> We do not guarantee backwards compatibility of private symbols. Private
> symbols may change in any release. So you should stick with public ones.
>
OK.
>> 3.
>> How should an application generate error strings? The examples at
>> SSLsample do a very strange trick. On the other hand, selfserv on my
>> machine simply finds no error string (for example, when using a bad
>> certificate database, error "-8174").
>
> I suggest you look at SECU_PrintError for guidance. Sounds like you've
> found another bug in SSLSample.
>
SECU_PrintError seems to be for *printing* an error string rather than
*getting* one. Did you mean SECU_Strerror?
selfserv uses SECU_Strerror, but this is a private function. in
addition, on my machine it does not find an error string for -8174, for
example.
See also Wan-Teh Chang's reply.
>> 4.
>> It is explained that we can either configure a listen socket for SSL
>> using SSL_ConfigSecureServer(), or listen in the regular manner and then
>> configure enable SSL on the socket created by PR_Accept().
>
> EIther way, it is necessary to call SSL_ConfigSecureServer.
>
>> Is SSL_ConfigSecureServer() just an elegant way to enable SSL on all
>> sockets created from some listen socket, and nothing else? Does it add
>> any security?
>
> It is the sole means by which you configure the certificates and private
> keys on the SSL server socket.
>
I will rephrase my question: does it make any difference whether I do
the SSL configuration (1) on the listen socket, or (2) on the socket
created by PR_Accept (except the need to call SSL_ResetHandshake() in
the latter case) ?
By the way, the SSL reference seems to be incorrect in saying that
"SSL_ConfigSecureServer ... Configures a listen socket ...".
(http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1217647).
>> 5.
>> Is there a simple example of an NSS client and server? I understand that
>> the SSLsample example are not considered good enough. However, selfserv
>> and strsclnt are rather complicated, since they handle numerous
>> configuration options.
>
> SSLsample is the simplest example NSS has.
>
OK.
>> 6.
>> bug report - in function setupSSLSocket() of SSLsample/client.c, any
>> failure leads to closing tcpSocket, even after SSL_ImportFD(), which
>> replaces tcpSocket by sslSocket.
>
> It's not a bug. You will find that the value returned by SSL_ImportFD
> is the same as the value of "fd" (the second argument) passed to it.
>
OK. Although it would be safer to make sure that they are equal, I guess.
>> Thanks,
>> Yahel Zamir.
>
>
Could you find out why? -8174 is SEC_ERROR_BAD_DATABASE, a common
error code. SEC_ERROR_BAD_DATABASE is listed in the table:
http://lxr.mozilla.org/security/source/security/nss/cmd/lib/SECerrs.h#94
so SECU_Strerror should be able to find it. Does selfserv print
"security library: bad database" on the next line after "-8174"?
>>> 6.
>>> bug report - in function setupSSLSocket() of SSLsample/client.c, any
>>> failure leads to closing tcpSocket, even after SSL_ImportFD(), which
>>> replaces tcpSocket by sslSocket.
>>
>> It's not a bug. You will find that the value returned by SSL_ImportFD
>> is the same as the value of "fd" (the second argument) passed to it.
>>
>
> OK. Although it would be safer to make sure that they are equal, I guess.
I see what the confusion was. Nelson's right. The code is correct.
It is necessary to use a new variable for the return value of
SSL_ImportFD -- if we say
133 /* Import the socket into the SSL layer. */
134 tcpSocket = SSL_ImportFD(NULL, tcpSocket);
we will lose the original value of tcpSocket when SSL_ImportFD fails.
I agree a comment or an assertion would help clarify this subtle
point for people who are unfamiliar with NSPR's I/O layers.
133 /* Import the socket into the SSL layer. */
134 sslSocket = SSL_ImportFD(NULL, tcpSocket);
PORT_Assert(!sslSocket || sslSocket == tcpSocket);
Wan-Teh
My mistake. SECU_Strerror simply never gets called in my scenario.
By the way, currently it is declared in
<INSTALL-DIR>/mozilla/dist/private/nss/secutil.h.
Why not make SECU_Strerror public?