micromdm / scep

Go SCEP server
MIT License
329 stars 128 forks source link

Certificate renewal verification not working as expected #235

Open nagappa2011 opened 3 months ago

nagappa2011 commented 3 months ago

Hi Everyone, I am trying a few scenarios with this code base and seeing a behaviour and looking for confirmation on the same.

  1. Created CA and run the server.
  2. Clients send a PKCS request, and the server issues the certificate.
  3. Back up the existing CA and create a new CA (new cert and new private key), And run the server, it picks this new CA.
  4. On the client side, I deleted the csr.pem, kept client.key and client.pem as it is. The expectation was to send the renewal with the new CSR request. But going with the new CA (created in step 3). And the existing certificate (client.pem) was issued by old CA (created in step 1).
  5. On the server side, It still goes to DB and checks for the existing DN. I was expecting the error in ParsePKIMessage or in DecryptEnvelope as the existing certificate was issued by old CA.

it would be great help if someone gets back to me with the expected behaviour in this case. Thank you so much.

jessepeterson commented 3 months ago

I don't think I'm following. You completely removed the CA database, created a new one, and somehow it issues from the old CA db? That seems odd. Can you give a list of commands and what you expected at each step? Thanks!

nagappa2011 commented 3 months ago

@jessepeterson, I replaced the old CA with the new one. And issued a renewal request where the old CA signed the old client certificate and that was used in the renewal request. However, I expected that it would fail as the client certificate that was used in this renewal was issued by old CA and it should not issue the new certificate for this renewal. renewal is not verifying the current certificate chain. I understand correctly. PR: https://github.com/micromdm/scep/pull/183/files might solve this issue. But it is not yet pushed it seems.

jessepeterson commented 3 months ago

Yeah, the server doesn't really support "renewal" (as in, the SCEP protocol renewal type). It can only re-issue new certificates. Yes, #183 might be a solution. But that PR needs changes. Honestly I'd suggest taking a look at moving to https://github.com/smallstep/certificates :)

nagappa2011 commented 3 months ago

Thanks for the suggestion. I will start exploring this. Also, What is your opinion on just using the scep server part from the smallstep (https://github.com/smallstep/scep)? Does it cover the verification of for renewal message properly? which #183 is doing?

jessepeterson commented 3 months ago

smallstep's SCEP library was forked from this project: https://micromdm.io/blog/scepping-stone/ :)

hslatman commented 2 months ago

@nagappa2011 https://github.com/smallstep/scep is just the core SCEP library, and there's currently no ready to run server, as that's still in this repo. You can use the package and it should be able to process the RenewalReq message type, but you would have to implement the logic for verification yourself. That part would be similar to what's in https://github.com/micromdm/scep/pull/183.

In https://github.com/smallstep/certificates we haven't implemented renewal yet, because so far we haven't had someone in need for it, and also because it doesn't seem to be required in practice. We found that Windows and macOS SCEP clients go through a new certificate request from start, instead of using the old certificate and key to authenticate. But we'd be open to adding support for it if there's a real need.

nchinnannava-JNPR commented 2 months ago

@hslatman Thank you so much for the insights. When you say implement yourself, Does it mean in the application? or in the scep library. I will think about it.

hslatman commented 2 months ago

@nchinnannava-JNPR at the moment that would have to go into your own application. It's possible some helper functionality could eventually go into the core scep library, but this is mainly about a SCEP server supporting (or not) renewal through the RenewalReq, so that ought to go into the system that imports scep.

nchinnannava-JNPR commented 2 months ago

@hslatman Just wanted to get more information on this "Windows and macOS SCEP clients go through a new certificate request from start". When you say this, RenewalReq (17) message type not being used now? In this case, during certificate renewal, the client is still going to send re-enrol with PKCSReq(19). Do these operating system clients use self-signed certificates during renewal? Is renewal going to be the same process as enrolling, or are there any differences you see? Scep just needs to do challenge/CSR validations during renewal too? Thanks

hslatman commented 2 months ago

Yes, the process for renewal on those systems basically works like a new enrollment with PKCSReq. At least that's what we're seeing in practice with our CA implementation, and various versions of Windows, macOS and iOS performing SCEP requests.

As far as I can tell the process is the same for renewals as for the initial requests, and will thus indeed use a self-signed certificate every time, and it will indeed include the challenge on every request (or not, if not instructed to include a challenge value). It is likely implemented like that to keep things simple: less state to manage, so less potential for problems with stale or erroneous state. It's also possible a client will actively check for the capability to be available before trying to use RenewalReq by checking for the Renewal capability. In our CA we do return that by default, and clients still use PKCSReq to renew. The behavior might also be influenced by how a (or our) CA works as a whole, though, so it is advised to verify it yourself.

nchinnannava-JNPR commented 2 months ago

@hslatman Thank you so much for the detailed explanation. That clarified all my queries.

Best Regards