@@ -54,6 +54,12 @@ type csrRequestJSON struct {
5454 KeyLength int `json:"KeyLength"`
5555}
5656
57+ type replaceCertData struct {
58+ CertData string `json:"CertData"`
59+ KeyData string `json:"KeyData"`
60+ Reload bool `json:"Reload"`
61+ }
62+
5763// ensure we fully implement the RequestHandlerHTTP type
5864var _ RequestHandlerHTTP = & HandlerAdmin {}
5965
@@ -148,11 +154,9 @@ func (l *HandlerWebAdmin) serveCertsCSR(res http.ResponseWriter, req *http.Reque
148154 if ! l .requirePostMethod (res , req ) {
149155 return
150156 }
151-
152157 // extract json payload
153158 decoder := json .NewDecoder (req .Body )
154159 decoder .DisallowUnknownFields ()
155-
156160 data := csrRequestJSON {}
157161 err := decoder .Decode (& data )
158162 if err != nil {
@@ -165,7 +169,6 @@ func (l *HandlerWebAdmin) serveCertsCSR(res http.ResponseWriter, req *http.Reque
165169
166170 return
167171 }
168-
169172 if data .HostName == "" {
170173 res .Header ().Set ("Content-Type" , "application/json" )
171174 res .WriteHeader (http .StatusBadRequest )
@@ -184,7 +187,12 @@ func (l *HandlerWebAdmin) serveCertsCSR(res http.ResponseWriter, req *http.Reque
184187 }
185188 privateKey , err = rsa .GenerateKey (rand .Reader , data .KeyLength )
186189 } else {
187- privateKey , err = l .readPrivateKey ()
190+ defaultSection := l .Handler .snc .config .Section ("/settings/default" )
191+ keyFile , ok := defaultSection .GetString ("certificate key" )
192+ if ! ok {
193+ l .sendError (res , fmt .Errorf ("could not read certificate location from config" ))
194+ }
195+ privateKey , err = l .readPrivateKey (keyFile )
188196 }
189197 if err != nil {
190198 l .sendError (res , err )
@@ -203,8 +211,10 @@ func (l *HandlerWebAdmin) serveCertsCSR(res http.ResponseWriter, req *http.Reque
203211 defSection := l .Handler .snc .config .Section ("/settings/default" )
204212
205213 keyFile , _ := defSection .GetString ("certificate key" )
214+ keyFileTemp := keyFile + ".tmp"
215+
206216 privateKeyBytes := x509 .MarshalPKCS1PrivateKey (privateKey )
207- if err = os .WriteFile (keyFile , pem .EncodeToMemory (& pem.Block {Type : "RSA PRIVATE KEY" , Bytes : privateKeyBytes }), 0o600 ); err != nil {
217+ if err = os .WriteFile (keyFileTemp , pem .EncodeToMemory (& pem.Block {Type : "RSA PRIVATE KEY" , Bytes : privateKeyBytes }), 0o600 ); err != nil {
208218 l .sendError (res , fmt .Errorf ("failed to write certificate key file %s: %s" , keyFile , err .Error ()))
209219
210220 return
@@ -247,13 +257,8 @@ func (l *HandlerWebAdmin) createCSR(data *csrRequestJSON, privateKey *rsa.Privat
247257 return csrPEM , nil
248258}
249259
250- func (l * HandlerWebAdmin ) readPrivateKey () (* rsa.PrivateKey , error ) {
260+ func (l * HandlerWebAdmin ) readPrivateKey (keyFile string ) (* rsa.PrivateKey , error ) {
251261 // read private key
252- defSection := l .Handler .snc .config .Section ("/settings/default" )
253- keyFile , ok := defSection .GetString ("certificate key" )
254- if ! ok {
255- return nil , fmt .Errorf ("could not read certificate location from config" )
256- }
257262 pemData , err := os .ReadFile (keyFile )
258263 if err != nil {
259264 return nil , fmt .Errorf ("could not read file: %s" , err .Error ())
@@ -288,12 +293,7 @@ func (l *HandlerWebAdmin) serveCertsReplace(res http.ResponseWriter, req *http.R
288293 // extract json payload
289294 decoder := json .NewDecoder (req .Body )
290295 decoder .DisallowUnknownFields ()
291- type postData struct {
292- CertData string `json:"CertData"`
293- KeyData string `json:"KeyData"`
294- Reload bool `json:"Reload"`
295- }
296- data := postData {}
296+ data := replaceCertData {}
297297 err := decoder .Decode (& data )
298298 if err != nil {
299299 res .Header ().Set ("Content-Type" , "application/json" )
@@ -306,29 +306,31 @@ func (l *HandlerWebAdmin) serveCertsReplace(res http.ResponseWriter, req *http.R
306306 return
307307 }
308308
309- certBytes := []byte {}
310- keyBytes := []byte {}
311- if data .CertData != "" {
312- certBytes , err = base64 .StdEncoding .DecodeString (data .CertData )
313- if err != nil {
314- l .sendError (res , fmt .Errorf ("failed to base64 decode certdata: %s" , err .Error ()))
315-
316- return
317- }
318- }
319-
320- if data .KeyData != "" {
321- keyBytes , err = base64 .StdEncoding .DecodeString (data .KeyData )
322- if err != nil {
323- l .sendError (res , fmt .Errorf ("failed to base64 decode keydata: %s" , err .Error ()))
324-
325- return
326- }
309+ certBytes , keyBytes , err := l .getBytesFromRaplacementStructData (res , data )
310+ if err != nil {
311+ return
327312 }
328313
329314 defSection := l .Handler .snc .config .Section ("/settings/default" )
330315 certFile , _ := defSection .GetString ("certificate" )
331316 keyFile , _ := defSection .GetString ("certificate key" )
317+ keyFileBak := keyFile + ".tmp"
318+ if data .KeyData == "" && data .CertData != "" {
319+ pubKey , certPublicKey := l .getRelevantPublicKeys (res , keyFileBak , certBytes )
320+ newPrivateKey , err := l .readPrivateKey (keyFileBak )
321+ if err != nil {
322+ l .sendError (res , err )
323+ }
324+ if pubKey .Equal (certPublicKey ) {
325+ privateKeyBytes := x509 .MarshalPKCS1PrivateKey (newPrivateKey )
326+ if err = os .WriteFile (keyFile , pem .EncodeToMemory (& pem.Block {Type : "RSA PRIVATE KEY" , Bytes : privateKeyBytes }), 0o600 ); err != nil {
327+ l .sendError (res , fmt .Errorf ("failed to write certificate key file %s: %s" , keyFile , err .Error ()))
328+
329+ return
330+ }
331+ os .Remove (keyFileBak )
332+ }
333+ }
332334
333335 if data .CertData != "" {
334336 if err := os .WriteFile (certFile , certBytes , 0o600 ); err != nil {
@@ -357,6 +359,52 @@ func (l *HandlerWebAdmin) serveCertsReplace(res http.ResponseWriter, req *http.R
357359 }
358360}
359361
362+ func (l * HandlerWebAdmin ) getBytesFromRaplacementStructData (res http.ResponseWriter , data replaceCertData ) (certBytes , keyBytes []byte , err error ) {
363+ if data .CertData != "" {
364+ certBytes , err = base64 .StdEncoding .DecodeString (data .CertData )
365+ if err != nil {
366+ l .sendError (res , fmt .Errorf ("failed to base64 decode certdata: %s" , err .Error ()))
367+
368+ return
369+ }
370+ }
371+
372+ if data .KeyData != "" {
373+ keyBytes , err = base64 .StdEncoding .DecodeString (data .KeyData )
374+ if err != nil {
375+ l .sendError (res , fmt .Errorf ("failed to base64 decode keydata: %s" , err .Error ()))
376+
377+ return
378+ }
379+ }
380+
381+ return
382+ }
383+
384+ func (l * HandlerWebAdmin ) getRelevantPublicKeys (res http.ResponseWriter , tempKeyFile string , certBytes []byte ) (privateKeyPubclicPart , certPublicKey * rsa.PublicKey ) {
385+ newPrivateKey , err := l .readPrivateKey (tempKeyFile )
386+
387+ if err != nil {
388+ l .sendError (res , err )
389+ }
390+ newPubKey := newPrivateKey .Public ()
391+ rsaNewPublicKey , ok := newPubKey .(* rsa.PublicKey )
392+ if ! ok {
393+ l .sendError (res , fmt .Errorf ("rsa public key in wrong format" ))
394+ }
395+ block , _ := pem .Decode (certBytes )
396+ newCert , err := x509 .ParseCertificate (block .Bytes )
397+ if err != nil {
398+ l .sendError (res , err )
399+ }
400+ newCertPublicKey , ok := newCert .PublicKey .(* rsa.PublicKey )
401+ if ! ok {
402+ l .sendError (res , fmt .Errorf ("rsa public key from csr in wrong format" ))
403+ }
404+
405+ return rsaNewPublicKey , newCertPublicKey
406+ }
407+
360408func (l * HandlerWebAdmin ) serveUpdate (res http.ResponseWriter , req * http.Request ) {
361409 if ! l .requirePostMethod (res , req ) {
362410 return
0 commit comments