package service import ( "crypto/rand" "crypto/rsa" "crypto/sha256" "encoding/hex" "encoding/json" "errors" "io/ioutil" "net/http" ) import "golang.org/x/crypto/blowfish" type Status int const ( OK Status = iota WAITING ERROR ) type BaseMessage struct { Signature string } type httpServer struct { manager *Manager status Status } type CreateCSRRequest struct { *BaseMessage Hostname string } type CreateCSRResponse struct { *BaseMessage CSR string `json:"csr"` } type UpdateOpenVPNConfigRequest struct { *BaseMessage Config string } type DeliverCertificateRequest struct { *BaseMessage Certificate string } func NewHttpServer(manager *Manager) *httpServer { return &httpServer{manager, WAITING} } func (it *httpServer) Start() { http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { writer.WriteHeader(200) writer.Write([]byte("Don't")) }) http.HandleFunc("/create-csr", func(writer http.ResponseWriter, request *http.Request) { req := &CreateCSRRequest{} err := it.verifyRequest(request, req) if err != nil { writer.WriteHeader(400) return } csr, err := it.manager.CreateCSR(req.Hostname) if err != nil { writer.WriteHeader(500) return } it.writeResponse(writer, CreateCSRResponse{ CSR: string(csr), }) }) http.HandleFunc("/deliver-crt", func(writer http.ResponseWriter, request *http.Request) { req := &DeliverCertificateRequest{} err := it.verifyRequest(request, req) if err != nil { writer.WriteHeader(400) return } err = it.manager.UpdateCertificate(req.Certificate) if err != nil { writer.WriteHeader(500) return } it.manager.openVPN.Start() }) http.HandleFunc("/update-openvpn-config", func(writer http.ResponseWriter, request *http.Request) { req := &UpdateOpenVPNConfigRequest{} err := it.verifyRequest(request, req) if err != nil { writer.WriteHeader(400) return } err = it.manager.openVPN.UpdateConfig(req.Config) if err != nil { writer.WriteHeader(500) return } it.manager.openVPN.Restart() }) http.ListenAndServe(":7864", nil) } func (it *httpServer) writeResponse(writer http.ResponseWriter, v interface{}) error { passwordAndIV := make([]byte, 48) _, err := rand.Read(passwordAndIV) if err != nil { return err } encPasswordAndIV, err := rsa.EncryptPKCS1v15(rand.Reader, it.manager.CAPublicKey(), passwordAndIV) if err != nil { return err } _, err = writer.Write([]byte(hex.EncodeToString(encPasswordAndIV))) if err != nil { return err } password := passwordAndIV[:32] iv := passwordAndIV[32:] cipher, err := blowfish.NewSaltedCipher(password, iv) if err != nil { return err } hashedFingerpint := sha256.Sum256(it.manager.GetServerFingerprint()) plainSignature, err := rsa.SignPKCS1v15(rand.Reader, it.manager.privateKey, 0, hashedFingerpint[:]) if err != nil { return err } sign, ok := v.(*BaseMessage) if !ok { return errors.New("Given message can't be signed") } sign.Signature = hex.EncodeToString(plainSignature) body, err := json.Marshal(v) if err != nil { return err } encBody := make([]byte, len(body)) cipher.Encrypt(encBody, body) writer.Write([]byte(hex.EncodeToString(encBody))) return nil } func (it *httpServer) verifyRequest(r *http.Request, v interface{}) (error) { all, err := ioutil.ReadAll(hex.NewDecoder(r.Body)) if err != nil { return err } encPasswordAndIV := all[:256] encBody := all[256:] passwordAndIV, err := rsa.DecryptPKCS1v15(rand.Reader, it.manager.privateKey, encPasswordAndIV) if err != nil { return err } password := passwordAndIV[:32] iv := passwordAndIV[32:] cipher, err := blowfish.NewSaltedCipher(password, iv) if err != nil { return err } body := make([]byte, len(encBody)) cipher.Decrypt(body, encBody) err = json.Unmarshal(body, v) if err != nil { return err } baseReq, ok := v.(*BaseMessage) if !ok { return errors.New("non-base request") } signature, err := hex.DecodeString(baseReq.Signature) if err != nil { return err } fingerprint := it.manager.GetServerFingerprint() fingerprintHashed := sha256.Sum256(fingerprint) err = rsa.VerifyPKCS1v15(it.manager.CAPublicKey(), 0, fingerprintHashed[:], signature) return err }