// FailOnError exits and prints an error message if we encountered a problem func FailOnError(err error, msg string) { if err != nil { logger := blog.Get() logger.AuditErr(fmt.Sprintf("%s: %s", msg, err)) fmt.Fprintf(os.Stderr, "%s: %s\n", msg, err) os.Exit(1) } }
// FailOnError exits and prints an error message if we encountered a problem func FailOnError(err error, msg string) { if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 logger := blog.Get() logger.AuditErr(fmt.Sprintf("%s: %s", msg, err)) fmt.Fprintf(os.Stderr, "%s: %s\n", msg, err) os.Exit(1) } }
// New constructs a Policy Authority. // TODO(https://github.com/letsencrypt/boulder/issues/1616): Remove the _ bool // argument (used to be enforceWhitelist). Update all callers. func New(challengeTypes map[string]bool) (*AuthorityImpl, error) { pa := AuthorityImpl{ log: blog.Get(), enabledChallenges: challengeTypes, // We don't need real randomness for this. pseudoRNG: rand.New(rand.NewSource(99)), } return &pa, nil }
// Clock functions similarly to clock.Default(), but the returned value can be // changed using the FAKECLOCK environment variable if the 'integration' build // flag is set. // // The FAKECLOCK env var is in the time.UnixDate format, returned by `date -d`. func Clock() clock.Clock { if tgt := os.Getenv("FAKECLOCK"); tgt != "" { targetTime, err := time.Parse(time.UnixDate, tgt) FailOnError(err, fmt.Sprintf("cmd.Clock: bad format for FAKECLOCK: %v\n", err)) cl := clock.NewFake() cl.Set(targetTime) blog.Get().Info(fmt.Sprintf("Time was set to %v via FAKECLOCK", targetTime)) return cl } return clock.Default() }
// NewWebFrontEndImpl constructs a web service for Boulder func NewWebFrontEndImpl(stats statsd.Statter, clk clock.Clock, keyPolicy core.KeyPolicy) (WebFrontEndImpl, error) { logger := blog.Get() nonceService, err := core.NewNonceService() if err != nil { return WebFrontEndImpl{}, err } return WebFrontEndImpl{ log: logger, clk: clk, nonceService: nonceService, stats: stats, keyPolicy: keyPolicy, }, nil }
// KeyDigest produces a padded, standard Base64-encoded SHA256 digest of a // provided public key. func KeyDigest(key crypto.PublicKey) (string, error) { switch t := key.(type) { case *jose.JsonWebKey: if t == nil { return "", fmt.Errorf("Cannot compute digest of nil key") } return KeyDigest(t.Key) case jose.JsonWebKey: return KeyDigest(t.Key) default: keyDER, err := x509.MarshalPKIXPublicKey(key) if err != nil { logger := blog.Get() logger.Debug(fmt.Sprintf("Problem marshaling public key: %s", err)) return "", err } spkiDigest := sha256.Sum256(keyDER) return base64.StdEncoding.EncodeToString(spkiDigest[0:32]), nil } }
// NewAmqpRPCServer creates a new RPC server for the given queue and will begin // consuming requests from the queue. To start the server you must call Start(). func NewAmqpRPCServer(amqpConf *cmd.AMQPConfig, maxConcurrentRPCServerRequests int64, stats statsd.Statter) (*AmqpRPCServer, error) { log := blog.Get() reconnectBase := amqpConf.ReconnectTimeouts.Base.Duration if reconnectBase == 0 { reconnectBase = 20 * time.Millisecond } reconnectMax := amqpConf.ReconnectTimeouts.Max.Duration if reconnectMax == 0 { reconnectMax = time.Minute } return &AmqpRPCServer{ serverQueue: amqpConf.ServiceQueue, connection: newAMQPConnector(amqpConf.ServiceQueue, reconnectBase, reconnectMax), log: log, dispatchTable: make(map[string]messageHandler), maxConcurrentRPCServerRequests: maxConcurrentRPCServerRequests, clk: clock.Default(), stats: stats, }, nil }
func handleConn(conn net.Conn) { defer conn.Close() auditlogger := blog.Get() auditlogger.Info(fmt.Sprintf("mail-test-srv: Got connection from %s", conn.RemoteAddr())) readBuf := bufio.NewReader(conn) conn.Write([]byte("220 smtp.example.com ESMTP\r\n")) if err := expectLine(readBuf, "EHLO localhost"); err != nil { log.Printf("mail-test-srv: %s: %v\n", conn.RemoteAddr(), err) return } conn.Write([]byte("250-PIPELINING\r\n")) conn.Write([]byte("250-AUTH PLAIN LOGIN\r\n")) conn.Write([]byte("250 8BITMIME\r\n")) if err := expectLine(readBuf, "AUTH PLAIN AGNlcnQtbWFzdGVyQGV4YW1wbGUuY29tAHBhc3N3b3Jk"); err != nil { log.Printf("mail-test-srv: %s: %v\n", conn.RemoteAddr(), err) return } conn.Write([]byte("235 2.7.0 Authentication successful\r\n")) auditlogger.Info(fmt.Sprintf("mail-test-srv: Successful auth from %s", conn.RemoteAddr())) // necessary commands: // MAIL RCPT DATA QUIT var fromAddr string var toAddr []string clearState := func() { fromAddr = "" toAddr = nil } reader := bufio.NewScanner(readBuf) for reader.Scan() { line := reader.Text() cmdSplit := strings.SplitN(line, " ", 2) cmd := cmdSplit[0] switch cmd { case "QUIT": conn.Write([]byte("221 Bye \r\n")) break case "RSET": clearState() conn.Write(smtpOk250) case "NOOP": conn.Write(smtpOk250) case "MAIL": clearState() matches := mailFromRegex.FindStringSubmatch(line) if matches == nil { log.Panicf("mail-test-srv: %s: MAIL FROM parse error\n", conn.RemoteAddr()) } addr, err := mail.ParseAddress(matches[1]) if err != nil { log.Panicf("mail-test-srv: %s: addr parse error: %v\n", conn.RemoteAddr(), err) } fromAddr = addr.Address conn.Write(smtpOk250) case "RCPT": matches := rcptToRegex.FindStringSubmatch(line) if matches == nil { conn.Write(smtpErr501) continue } addr, err := mail.ParseAddress(matches[1]) if err != nil { log.Panicf("mail-test-srv: %s: addr parse error: %v\n", conn.RemoteAddr(), err) } toAddr = append(toAddr, addr.Address) conn.Write(smtpOk250) case "DATA": conn.Write([]byte("354 Start mail input \r\n")) var msgBuf bytes.Buffer for reader.Scan() { line := reader.Text() msgBuf.WriteString(line) msgBuf.WriteString("\r\n") if strings.HasSuffix(msgBuf.String(), "\r\n.\r\n") { break } } if reader.Err() != nil { log.Printf("mail-test-srv: read from %s: %v\n", conn.RemoteAddr(), reader.Err()) return } mailResult := rcvdMail{ From: fromAddr, Mail: msgBuf.String(), } allMailMutex.Lock() for _, rcpt := range toAddr { mailResult.To = rcpt allReceivedMail = append(allReceivedMail, mailResult) log.Printf("mail-test-srv: Got mail: %s -> %s\n", fromAddr, rcpt) } allMailMutex.Unlock() conn.Write([]byte("250 Got mail \r\n")) clearState() } } if reader.Err() != nil { log.Printf("mail-test-srv: read from %s: %s\n", conn.RemoteAddr(), reader.Err()) } }
func errorCondition(method string, err error, obj interface{}) { log := blog.Get() log.AuditErr(fmt.Sprintf("Error condition. method: %s err: %s data: %+v", method, err, obj)) }
func improperMessage(method string, err error, obj interface{}) { log := blog.Get() log.AuditErr(fmt.Sprintf("Improper message. method: %s err: %s data: %+v", method, err, obj)) }
// NewAmqpRPCClient constructs an RPC client using AMQP func NewAmqpRPCClient( clientQueuePrefix string, amqpConf *cmd.AMQPConfig, rpcConf *cmd.RPCServerConfig, stats metrics.Scope, ) (rpc *AmqpRPCCLient, err error) { stats = stats.NewScope("RPC") hostname, err := os.Hostname() if err != nil { return nil, err } randID := make([]byte, 3) _, err = rand.Read(randID) if err != nil { return nil, err } clientQueue := fmt.Sprintf("%s.%s.%x", clientQueuePrefix, hostname, randID) reconnectBase := amqpConf.ReconnectTimeouts.Base.Duration if reconnectBase == 0 { reconnectBase = 20 * time.Millisecond } reconnectMax := amqpConf.ReconnectTimeouts.Max.Duration if reconnectMax == 0 { reconnectMax = time.Minute } timeout := rpcConf.RPCTimeout.Duration if timeout == 0 { timeout = 10 * time.Second } rpc = &AmqpRPCCLient{ serverQueue: rpcConf.Server, clientQueue: clientQueue, connection: newAMQPConnector(clientQueue, reconnectBase, reconnectMax), pending: make(map[string]chan []byte), timeout: timeout, log: blog.Get(), stats: stats, } err = rpc.connection.connect(amqpConf) if err != nil { return nil, err } go func() { for { select { case msg, ok := <-rpc.connection.messages(): if ok { corrID := msg.CorrelationId rpc.mu.RLock() responseChan, present := rpc.pending[corrID] rpc.mu.RUnlock() if !present { // occurs when a request is timed out and the arrives // afterwards stats.Inc("AfterTimeoutResponseArrivals."+clientQueuePrefix, 1) continue } responseChan <- msg.Body rpc.mu.Lock() delete(rpc.pending, corrID) rpc.mu.Unlock() } else { // chan has been closed by rpc.connection.Cancel rpc.log.Info(fmt.Sprintf(" [!] Client reply channel closed: %s", rpc.clientQueue)) continue } case err = <-rpc.connection.closeChannel(): rpc.log.Info(fmt.Sprintf(" [!] Client reply channel closed : %s", rpc.clientQueue)) rpc.connection.reconnect(amqpConf, rpc.log) } } }() return rpc, err }
// makeAmqpChannel sets an AMQP connection up using SSL if configuration is provided func makeAmqpChannel(conf *cmd.AMQPConfig) (*amqp.Channel, error) { var conn *amqp.Connection var err error log := blog.Get() serverURL, err := conf.ServerURL() if err != nil { return nil, err } if conf.Insecure == true { // If the Insecure flag is true, then just go ahead and connect conn, err = amqp.Dial(serverURL) } else { // The insecure flag is false or not set, so we need to load up the options log.Info("AMQPS: Loading TLS Options.") if strings.HasPrefix(serverURL, "amqps") == false { err = fmt.Errorf("AMQPS: Not using an AMQPS URL. To use AMQP instead of AMQPS, set insecure=true") return nil, err } if conf.TLS == nil { err = fmt.Errorf("AMQPS: No TLS configuration provided. To use AMQP instead of AMQPS, set insecure=true") return nil, err } cfg := new(tls.Config) // If the configuration specified a certificate (or key), load them if conf.TLS.CertFile != nil || conf.TLS.KeyFile != nil { // But they have to give both. if conf.TLS.CertFile == nil || conf.TLS.KeyFile == nil { err = fmt.Errorf("AMQPS: You must set both of the configuration values AMQP.TLS.KeyFile and AMQP.TLS.CertFile") return nil, err } cert, err := tls.LoadX509KeyPair(*conf.TLS.CertFile, *conf.TLS.KeyFile) if err != nil { err = fmt.Errorf("AMQPS: Could not load Client Certificate or Key: %s", err) return nil, err } log.Info("AMQPS: Configured client certificate for AMQPS.") cfg.Certificates = append(cfg.Certificates, cert) } // If the configuration specified a CA certificate, make it the only // available root. if conf.TLS.CACertFile != nil { cfg.RootCAs = x509.NewCertPool() ca, err := ioutil.ReadFile(*conf.TLS.CACertFile) if err != nil { err = fmt.Errorf("AMQPS: Could not load CA Certificate: %s", err) return nil, err } cfg.RootCAs.AppendCertsFromPEM(ca) log.Info("AMQPS: Configured CA certificate for AMQPS.") } conn, err = amqp.DialTLS(serverURL, cfg) } if err != nil { return nil, err } return conn.Channel() }
// NewCertificateAuthorityImpl creates a CA instance that can sign certificates // from a single issuer (the first first in the issers slice), and can sign OCSP // for any of the issuer certificates provided. func NewCertificateAuthorityImpl( config cmd.CAConfig, clk clock.Clock, stats statsd.Statter, issuers []Issuer, keyPolicy core.KeyPolicy, ) (*CertificateAuthorityImpl, error) { var ca *CertificateAuthorityImpl var err error logger := blog.Get() if config.SerialPrefix <= 0 || config.SerialPrefix >= 256 { err = errors.New("Must have a positive non-zero serial prefix less than 256 for CA.") return nil, err } // CFSSL requires processing JSON configs through its own LoadConfig, so we // serialize and then deserialize. cfsslJSON, err := json.Marshal(config.CFSSL) if err != nil { return nil, err } cfsslConfigObj, err := cfsslConfig.LoadConfig(cfsslJSON) if err != nil { return nil, err } if config.LifespanOCSP.Duration == 0 { return nil, errors.New("Config must specify an OCSP lifespan period.") } internalIssuers, err := makeInternalIssuers( issuers, cfsslConfigObj.Signing, config.LifespanOCSP.Duration) if err != nil { return nil, err } defaultIssuer := internalIssuers[issuers[0].Cert.Subject.CommonName] rsaProfile := config.RSAProfile ecdsaProfile := config.ECDSAProfile if rsaProfile == "" || ecdsaProfile == "" { return nil, errors.New("must specify rsaProfile and ecdsaProfile") } ca = &CertificateAuthorityImpl{ issuers: internalIssuers, defaultIssuer: defaultIssuer, rsaProfile: rsaProfile, ecdsaProfile: ecdsaProfile, prefix: config.SerialPrefix, clk: clk, log: logger, stats: stats, keyPolicy: keyPolicy, forceCNFromSAN: !config.DoNotForceCN, // Note the inversion here enableMustStaple: config.EnableMustStaple, } if config.Expiry == "" { return nil, errors.New("Config must specify an expiry period.") } ca.validityPeriod, err = time.ParseDuration(config.Expiry) if err != nil { return nil, err } ca.maxNames = config.MaxNames return ca, nil }
// This is somewhat gross but can be pared down a bit once the publisher and this // are fully smooshed together func newUpdater( stats statsd.Statter, clk clock.Clock, dbMap *gorp.DbMap, ca core.CertificateAuthority, pub core.Publisher, sac core.StorageAuthority, config cmd.OCSPUpdaterConfig, numLogs int, issuerPath string, ) (*OCSPUpdater, error) { if config.NewCertificateBatchSize == 0 || config.OldOCSPBatchSize == 0 || config.MissingSCTBatchSize == 0 { return nil, fmt.Errorf("Loop batch sizes must be non-zero") } if config.NewCertificateWindow.Duration == 0 || config.OldOCSPWindow.Duration == 0 || config.MissingSCTWindow.Duration == 0 { return nil, fmt.Errorf("Loop window sizes must be non-zero") } log := blog.Get() updater := OCSPUpdater{ stats: stats, clk: clk, dbMap: dbMap, cac: ca, log: log, sac: sac, pubc: pub, numLogs: numLogs, ocspMinTimeToExpiry: config.OCSPMinTimeToExpiry.Duration, oldestIssuedSCT: config.OldestIssuedSCT.Duration, } // Setup loops updater.loops = []*looper{ { clk: clk, stats: stats, batchSize: config.NewCertificateBatchSize, tickDur: config.NewCertificateWindow.Duration, tickFunc: updater.newCertificateTick, name: "NewCertificates", failureBackoffFactor: config.SignFailureBackoffFactor, failureBackoffMax: config.SignFailureBackoffMax.Duration, }, { clk: clk, stats: stats, batchSize: config.OldOCSPBatchSize, tickDur: config.OldOCSPWindow.Duration, tickFunc: updater.oldOCSPResponsesTick, name: "OldOCSPResponses", failureBackoffFactor: config.SignFailureBackoffFactor, failureBackoffMax: config.SignFailureBackoffMax.Duration, }, // The missing SCT loop doesn't need to know about failureBackoffFactor or // failureBackoffMax as it doesn't make any calls to the CA { clk: clk, stats: stats, batchSize: config.MissingSCTBatchSize, tickDur: config.MissingSCTWindow.Duration, tickFunc: updater.missingReceiptsTick, name: "MissingSCTReceipts", }, } if config.RevokedCertificateBatchSize != 0 && config.RevokedCertificateWindow.Duration != 0 { updater.loops = append(updater.loops, &looper{ clk: clk, stats: stats, batchSize: config.RevokedCertificateBatchSize, tickDur: config.RevokedCertificateWindow.Duration, tickFunc: updater.revokedCertificatesTick, name: "RevokedCertificates", failureBackoffFactor: config.SignFailureBackoffFactor, failureBackoffMax: config.SignFailureBackoffMax.Duration, }) } // TODO(#1050): Remove this gate and the nil ccu checks below if config.AkamaiBaseURL != "" { issuer, err := core.LoadCert(issuerPath) ccu, err := akamai.NewCachePurgeClient( config.AkamaiBaseURL, config.AkamaiClientToken, config.AkamaiClientSecret, config.AkamaiAccessToken, config.AkamaiPurgeRetries, config.AkamaiPurgeRetryBackoff.Duration, log, stats, ) if err != nil { return nil, err } updater.ccu = ccu updater.issuer = issuer } return &updater, nil }
func (srv *mailSrv) handleConn(conn net.Conn) { defer conn.Close() srv.connNumberMutex.Lock() srv.connNumber++ srv.connNumberMutex.Unlock() auditlogger := blog.Get() auditlogger.Info(fmt.Sprintf("mail-test-srv: Got connection from %s", conn.RemoteAddr())) readBuf := bufio.NewReader(conn) conn.Write([]byte("220 smtp.example.com ESMTP\r\n")) if err := expectLine(readBuf, "EHLO localhost"); err != nil { log.Printf("mail-test-srv: %s: %v\n", conn.RemoteAddr(), err) return } conn.Write([]byte("250-PIPELINING\r\n")) conn.Write([]byte("250-AUTH PLAIN LOGIN\r\n")) conn.Write([]byte("250 8BITMIME\r\n")) if err := expectLine(readBuf, "AUTH PLAIN AGNlcnQtbWFzdGVyQGV4YW1wbGUuY29tAHBhc3N3b3Jk"); err != nil { log.Printf("mail-test-srv: %s: %v\n", conn.RemoteAddr(), err) return } conn.Write([]byte("235 2.7.0 Authentication successful\r\n")) auditlogger.Info(fmt.Sprintf("mail-test-srv: Successful auth from %s", conn.RemoteAddr())) // necessary commands: // MAIL RCPT DATA QUIT var fromAddr string var toAddr []string clearState := func() { fromAddr = "" toAddr = nil } reader := bufio.NewScanner(readBuf) for reader.Scan() { line := reader.Text() cmdSplit := strings.SplitN(line, " ", 2) cmd := cmdSplit[0] switch cmd { case "QUIT": conn.Write([]byte("221 Bye \r\n")) break case "RSET": clearState() conn.Write(smtpOk250) case "NOOP": conn.Write(smtpOk250) case "MAIL": srv.connNumberMutex.RLock() if srv.connNumber <= srv.closeFirst { // Half of the time, close cleanly to simulate the server side closing // unexpectedly. if srv.connNumber%2 == 0 { log.Printf( "mail-test-srv: connection # %d < -closeFirst parameter %d, disconnecting client. Bye!\n", srv.connNumber, srv.closeFirst) clearState() conn.Close() } else { // The rest of the time, simulate a stale connection timeout by sending // a SMTP 421 message. This replicates the timeout/close from issue // 2249 - https://github.com/letsencrypt/boulder/issues/2249 log.Printf( "mail-test-srv: connection # %d < -closeFirst parameter %d, disconnecting with 421. Bye!\n", srv.connNumber, srv.closeFirst) clearState() conn.Write([]byte("421 1.2.3 foo.bar.baz Error: timeout exceeded \r\n")) conn.Close() } } srv.connNumberMutex.RUnlock() clearState() matches := mailFromRegex.FindStringSubmatch(line) if matches == nil { log.Panicf("mail-test-srv: %s: MAIL FROM parse error\n", conn.RemoteAddr()) } addr, err := mail.ParseAddress(matches[1]) if err != nil { log.Panicf("mail-test-srv: %s: addr parse error: %v\n", conn.RemoteAddr(), err) } fromAddr = addr.Address conn.Write(smtpOk250) case "RCPT": matches := rcptToRegex.FindStringSubmatch(line) if matches == nil { conn.Write(smtpErr501) continue } addr, err := mail.ParseAddress(matches[1]) if err != nil { log.Panicf("mail-test-srv: %s: addr parse error: %v\n", conn.RemoteAddr(), err) } toAddr = append(toAddr, addr.Address) conn.Write(smtpOk250) case "DATA": conn.Write([]byte("354 Start mail input \r\n")) var msgBuf bytes.Buffer for reader.Scan() { line := reader.Text() msgBuf.WriteString(line) msgBuf.WriteString("\r\n") if strings.HasSuffix(msgBuf.String(), "\r\n.\r\n") { break } } if reader.Err() != nil { log.Printf("mail-test-srv: read from %s: %v\n", conn.RemoteAddr(), reader.Err()) return } mailResult := rcvdMail{ From: fromAddr, Mail: msgBuf.String(), } srv.allMailMutex.Lock() for _, rcpt := range toAddr { mailResult.To = rcpt srv.allReceivedMail = append(srv.allReceivedMail, mailResult) log.Printf("mail-test-srv: Got mail: %s -> %s\n", fromAddr, rcpt) } srv.allMailMutex.Unlock() conn.Write([]byte("250 Got mail \r\n")) clearState() } } if reader.Err() != nil { log.Printf("mail-test-srv: read from %s: %s\n", conn.RemoteAddr(), reader.Err()) } }
// NewRegistrationAuthorityServer constructs an RPC server func NewRegistrationAuthorityServer(rpc Server, impl core.RegistrationAuthority) error { log := blog.Get() rpc.Handle(MethodNewRegistration, func(ctx context.Context, req []byte) (response []byte, err error) { var rr registrationRequest if err = json.Unmarshal(req, &rr); err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodNewRegistration, err, req) return } reg, err := impl.NewRegistration(ctx, rr.Reg) if err != nil { return } response, err = json.Marshal(reg) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 errorCondition(MethodNewRegistration, err, req) return } return }) rpc.Handle(MethodNewAuthorization, func(ctx context.Context, req []byte) (response []byte, err error) { var ar authorizationRequest if err = json.Unmarshal(req, &ar); err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodNewAuthorization, err, req) return } authz, err := impl.NewAuthorization(ctx, ar.Authz, ar.RegID) if err != nil { return } response, err = json.Marshal(authz) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 errorCondition(MethodNewAuthorization, err, req) return } return }) rpc.Handle(MethodNewCertificate, func(ctx context.Context, req []byte) (response []byte, err error) { log.Info(fmt.Sprintf(" [.] Entering MethodNewCertificate")) var cr certificateRequest if err = json.Unmarshal(req, &cr); err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodNewCertificate, err, req) return } log.Info(fmt.Sprintf(" [.] No problem unmarshaling request")) cert, err := impl.NewCertificate(ctx, cr.Req, cr.RegID) if err != nil { return } log.Info(fmt.Sprintf(" [.] No problem issuing new cert")) response, err = json.Marshal(cert) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 errorCondition(MethodNewCertificate, err, req) return } return }) rpc.Handle(MethodUpdateRegistration, func(ctx context.Context, req []byte) (response []byte, err error) { var urReq updateRegistrationRequest err = json.Unmarshal(req, &urReq) if err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodUpdateRegistration, err, req) return } reg, err := impl.UpdateRegistration(ctx, urReq.Base, urReq.Update) if err != nil { return } response, err = json.Marshal(reg) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 errorCondition(MethodUpdateRegistration, err, req) return } return }) rpc.Handle(MethodUpdateAuthorization, func(ctx context.Context, req []byte) (response []byte, err error) { var uaReq updateAuthorizationRequest err = json.Unmarshal(req, &uaReq) if err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodUpdateAuthorization, err, req) return } newAuthz, err := impl.UpdateAuthorization(ctx, uaReq.Authz, uaReq.Index, uaReq.Response) if err != nil { return } response, err = json.Marshal(newAuthz) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 errorCondition(MethodUpdateAuthorization, err, req) return } return }) rpc.Handle(MethodRevokeCertificateWithReg, func(ctx context.Context, req []byte) (response []byte, err error) { var revReq struct { Cert []byte Reason core.RevocationCode RegID int64 } if err = json.Unmarshal(req, &revReq); err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodRevokeCertificateWithReg, err, req) return } cert, err := x509.ParseCertificate(revReq.Cert) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 return } err = impl.RevokeCertificateWithReg(ctx, *cert, revReq.Reason, revReq.RegID) return }) rpc.Handle(MethodAdministrativelyRevokeCertificate, func(ctx context.Context, req []byte) (response []byte, err error) { var revReq struct { Cert []byte Reason core.RevocationCode User string } if err = json.Unmarshal(req, &revReq); err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodAdministrativelyRevokeCertificate, err, req) return } cert, err := x509.ParseCertificate(revReq.Cert) if err != nil { // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 return } err = impl.AdministrativelyRevokeCertificate(ctx, *cert, revReq.Reason, revReq.User) return }) rpc.Handle(MethodOnValidationUpdate, func(ctx context.Context, req []byte) (response []byte, err error) { var authz core.Authorization if err = json.Unmarshal(req, &authz); err != nil { // AUDIT[ Improper Messages ] 0786b6f2-91ca-4f48-9883-842a19084c64 improperMessage(MethodOnValidationUpdate, err, req) return } err = impl.OnValidationUpdate(ctx, authz) return }) return nil }