On Friday, January 20, 2017 16:41:35 Pawel Veselov wrote: > On Fri, Jan 20, 2017 at 3:35 AM, Kamil Dudka <[email protected]> wrote: > > On Thursday, January 19, 2017 13:39:44 Pawel Veselov wrote: > >> Things work perfectly fine if I use the database, i.e. no MT problems. > >> Unfortunately, this is not a workaround to what I'm trying to achieve, > >> but it is pointing to nss-pem as a culprit, isn't it? > > > > Exactly. > > I tried using PKCS#12 format for authenticating, but I can't make it work > either. I set the certificate type to P12, but simply get "NSS error -8018 > (SEC_ERROR_UNKNOWN_PKCS11_ERROR)". Curl application simply rejects P12 > certificate type, so don't know what's up with that.
PKCS #12 is not supported by nss-pem (and not fully supported by nss either): https://bugzilla.redhat.com/1220573 > >> Anywhere in particular you'd like me to dig in there? > > > > The nss-pem module maintains a global array of objects named pem_objs. I > > guess it could be a problem if accesses to the array were not > > synchronized. > > But they should be thanks to the patch I referenced in my previous reply. > > Well, I'm not familiar with curl or nss code so it's not easy for me to > understand this. > > I'm looking at the code in nss_create_object, and is already a bit confused. > On the face of it it looks like the method creates some sort of "slots" > with NSS library, and there are ever only two potential names for these > slots - "PEM Token #0" or "PEM Token #1", depending on whether the > certificate being loaded is CA or not. Those are PKCS #11 slots -- an abstraction designed mostly for HW devices. nss-pem uses the PKCS #11 API to access certificates/keys from files. The slots are created during nss-pem module load. #0 is used for CA certificates and #1 is used for client certificates (and the corresponding private keys). I believe there can be multiple certificates loaded in each slot. I was told that there could be a problem if multiple _encrypted_ private keys were used at a time but I have not tested this scenario yet. > The function uses this slot during its execution, only locking it out when > the slot is being "found" (in nss_find_slot_by_name). I see that > PK11_CreateGenericObject() function uses a full lock when working with the > slot (EnterSlotMonitor/ExitSlotMonitor). The private key is loaded > separately. I haven't figured out all the logic, but the following sequence > strikes me as odd, I don't understand how things would work in this > case. PK11_CreateGenericObject() is used just to load the certificate/key from file. They are later accessed from the SelectClientCert() hook during the handshake. > Consider nss_load_key (it doesn't matter what's going here, I just see that > the slot object is freely used by multiple threads that seem to store some > information into it, which can be easily overwritten by other threads). > > thread#1 calls nss_create_object on key#1 > thread#2 calls nss_create_object on key#2 > thread#1 calls PK11_Authenticate (password) > > At that last point, the only input is slot ID and password, I don't > see how it can possible know to operate on key#1, and not key#2... Good point. That is exactly the reason why I asked whether the private keys are encrypted or not. The password is only used for encrypted private keys. > If you could please help me understand how the MT is realized on these > slots, and where does it happen that certificate/keys are actually > written out to the TCP socket, it would be very helpful. The > documentation for PK11 is scarce to > come about (if you have a pointer to that, it'd be very helpful as well :) ) > > Are your private keys encrypted? > > They are not encrypted. > > >> P.S. I also discovered that if database is used (even if it just > >> exists, may be it needs to have a CA, may be it doesn't), then > >> CURLOPT_CAINFO is ignored, or at least the cert that is provided by it > >> is no longer trusted. May be because the same cert is in the DB, and > >> without the C flag. If it is the latter, it is probably still a > >> problem, because if I say I need to trust cert X, there is no other > >> way for me to do it (if it is a system database, for example). > > > > You can try it with your own (e.g. empty) NSS database. You can set the > > $SSL_DIR environment variable to make libcurl use a different database. > > It's a stretch, sure, but the problem is: > * server's cert is signed with caXX > * client's cert is signed with caXX (same CA) > * you import client's chain into the cert database (CA gets imported, but > left in there without trust) > * You don't want to enable trust for this CA for all connections > * You only want to enable trusting the CA explicitly when you need to. > * NSS always picks caXX from the database, even if it is specified as > "trusted" separately, and because it's not marked as trusted in the DB, > doesn't accept server's certificate. Could be. I am definitely not an expert in this area. I would suggest to open a bug against NSS regarding the issue. > P.P.S. > > I also noticed this other thing in the code, may be I'm wrong. > The documentation says that to avoid conflicts between using file names and > certificate aliases for NSS, the use should prepend './' to the relative > file names. However, the code (nss_load_cert) checks if the file exists > first. So if there is a file at CWD/nick, it's not possible to use the > nickname, no? It should not happen. If you pass a certificate name without a slash, dup_nickname() will return a non-NULL pointer, which prevents cert_stuff() and consequently nss_load_cert() from being called at all. If you have a reproducer for the above mentioned issue, I would be certainly interested. Kamil ------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.haxx.se/mail/etiquette.html
