Now Zangtumb will create its own selfsigned certificates
							parent
							
								
									71a9b231e3
								
							
						
					
					
						commit
						ef4187459e
					
				
							
								
								
									
										12
									
								
								handler.go
								
								
								
								
							
							
						
						
									
										12
									
								
								handler.go
								
								
								
								
							| 
						 | 
				
			
			@ -5,11 +5,9 @@ import (
 | 
			
		|||
	"log"
 | 
			
		||||
	"net"
 | 
			
		||||
    "time"
 | 
			
		||||
	
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	ZangSmtpServer.HandlerRcpt = handlerRcpt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func mailHandler(origin net.Addr, from string, to []string, data []byte) {
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +24,7 @@ func mailHandler(origin net.Addr, from string, to []string, data []byte) {
 | 
			
		|||
			if dataErr := SmtpSession.Data(bytes.NewReader(data)); dataErr != nil {
 | 
			
		||||
				log.Println("Problem Saving Message: ", dataErr.Error())
 | 
			
		||||
			}
 | 
			
		||||
			log.Println("Session is: ", SmtpSession)
 | 
			
		||||
			
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Println(rcptErr)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -40,14 +38,14 @@ func handlerRcpt(remoteAddr net.Addr, from string, to string) bool {
 | 
			
		|||
 | 
			
		||||
	log.Println("CHECK #2 Rcpt to:", to)
 | 
			
		||||
	if !SmtpBackend.CheckValidRcpt(to) {
 | 
			
		||||
		log.Printf("%s [ %s -> $s ] %s BAD!!!!", "YU NO MAIL!!! WE NU RELAY!!! ", from, to, remoteAddr.String() )
 | 
			
		||||
		log.Printf("%s [ %s -> %s ] %s BAD!!!!", "YU NO MAIL!!! WE NU RELAY!!! ", from, to, remoteAddr.String() )
 | 
			
		||||
		time.Sleep(10 * time.Second)
 | 
			
		||||
		return false
 | 
			
		||||
	}else{
 | 
			
		||||
		log.Printf("%s [ %s -> $s ] %s GOOD!!!!", "WE DO!!!", from, to, remoteAddr.String() )
 | 
			
		||||
		log.Printf("%s [ %s -> %s ] %s GOOD!!!!", "WE DO!!!", from, to, remoteAddr.String() )
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								run.sh
								
								
								
								
							
							
						
						
									
										2
									
								
								run.sh
								
								
								
								
							| 
						 | 
				
			
			@ -8,7 +8,7 @@ export LISTEN=":1025"
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
##SESSION
 | 
			
		||||
export RECIPIENTS="./recipients.conf"
 | 
			
		||||
export RECIPIENTS="./recipients.conf.example"
 | 
			
		||||
export MAILFOLDER="mail"
 | 
			
		||||
 | 
			
		||||
##MAIN
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,9 +41,10 @@ type AuthHandler func(remoteAddr net.Addr, mechanism string, username []byte, pa
 | 
			
		|||
// ListenAndServe listens on the TCP network address addr
 | 
			
		||||
// and then calls Serve with handler to handle requests
 | 
			
		||||
// on incoming connections.
 | 
			
		||||
func ListenAndServe(addr string, handler Handler, appname string, hostname string, instance *Server) error {
 | 
			
		||||
func ListenAndServe(addr string, handler Handler, rcpthandler HandlerRcpt, appname string, hostname string, instance *Server) error {
 | 
			
		||||
	srv := instance
 | 
			
		||||
	srv.Addr = addr
 | 
			
		||||
	srv.HandlerRcpt = rcpthandler
 | 
			
		||||
	srv.Handler = handler
 | 
			
		||||
	srv.Appname = appname
 | 
			
		||||
	srv.Hostname = hostname
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,298 @@
 | 
			
		|||
package main
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
 | 
			
		||||
	"crypto/ecdsa"
 | 
			
		||||
 | 
			
		||||
	"crypto/ed25519"
 | 
			
		||||
 | 
			
		||||
	"crypto/elliptic"
 | 
			
		||||
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
 | 
			
		||||
	"crypto/x509/pkix"
 | 
			
		||||
 | 
			
		||||
	"encoding/pem"
 | 
			
		||||
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"math/big"
 | 
			
		||||
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func publicKey(priv interface{}) interface{} {
 | 
			
		||||
 | 
			
		||||
	switch k := priv.(type) {
 | 
			
		||||
 | 
			
		||||
	case *rsa.PrivateKey:
 | 
			
		||||
 | 
			
		||||
		return &k.PublicKey
 | 
			
		||||
 | 
			
		||||
	case *ecdsa.PrivateKey:
 | 
			
		||||
 | 
			
		||||
		return &k.PublicKey
 | 
			
		||||
 | 
			
		||||
	case ed25519.PrivateKey:
 | 
			
		||||
 | 
			
		||||
		return k.Public().(ed25519.PublicKey)
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func ZMakecert() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		host       :=  ZangSmtpServer.Hostname
 | 
			
		||||
	
 | 
			
		||||
		validFrom  := ""
 | 
			
		||||
	
 | 
			
		||||
		validFor   := time.Duration(3650 * 24 * time.Hour) 
 | 
			
		||||
	
 | 
			
		||||
		isCA       := false 
 | 
			
		||||
	
 | 
			
		||||
		rsaBits    := 4096
 | 
			
		||||
	
 | 
			
		||||
		ecdsaCurve := "P256" 
 | 
			
		||||
	
 | 
			
		||||
		ed25519Key := true
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	var priv interface{}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	switch ecdsaCurve {
 | 
			
		||||
 | 
			
		||||
	case "":
 | 
			
		||||
 | 
			
		||||
		if ed25519Key {
 | 
			
		||||
 | 
			
		||||
			_, priv, err = ed25519.GenerateKey(rand.Reader)
 | 
			
		||||
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			priv, err = rsa.GenerateKey(rand.Reader, rsaBits)
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case "P224":
 | 
			
		||||
 | 
			
		||||
		priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
 | 
			
		||||
 | 
			
		||||
	case "P256":
 | 
			
		||||
 | 
			
		||||
		priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | 
			
		||||
 | 
			
		||||
	case "P384":
 | 
			
		||||
 | 
			
		||||
		priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
 | 
			
		||||
 | 
			
		||||
	case "P521":
 | 
			
		||||
 | 
			
		||||
		priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Unrecognized elliptic curve: %q", ecdsaCurve)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to generate private key: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// ECDSA, ED25519 and RSA subject keys should have the DigitalSignature
 | 
			
		||||
 | 
			
		||||
	// KeyUsage bits set in the x509.Certificate template
 | 
			
		||||
 | 
			
		||||
	keyUsage := x509.KeyUsageDigitalSignature
 | 
			
		||||
 | 
			
		||||
	// Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In
 | 
			
		||||
 | 
			
		||||
	// the context of TLS this KeyUsage is particular to RSA key exchange and
 | 
			
		||||
 | 
			
		||||
	// authentication.
 | 
			
		||||
 | 
			
		||||
	if _, isRSA := priv.(*rsa.PrivateKey); isRSA {
 | 
			
		||||
 | 
			
		||||
		keyUsage |= x509.KeyUsageKeyEncipherment
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	var notBefore time.Time
 | 
			
		||||
 | 
			
		||||
	if len(validFrom) == 0 {
 | 
			
		||||
 | 
			
		||||
		notBefore = time.Now()
 | 
			
		||||
 | 
			
		||||
	} else {
 | 
			
		||||
 | 
			
		||||
		notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
 | 
			
		||||
			log.Fatalf("Failed to parse creation date: %v", err)
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	notAfter := notBefore.Add(validFor)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
 | 
			
		||||
 | 
			
		||||
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to generate serial number: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	template := x509.Certificate{
 | 
			
		||||
 | 
			
		||||
		SerialNumber: serialNumber,
 | 
			
		||||
 | 
			
		||||
		Subject: pkix.Name{
 | 
			
		||||
 | 
			
		||||
			Organization: []string{"ZangTumb SMTP Server Department"},
 | 
			
		||||
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		NotBefore: notBefore,
 | 
			
		||||
 | 
			
		||||
		NotAfter:  notAfter,
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		KeyUsage:              keyUsage,
 | 
			
		||||
 | 
			
		||||
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 | 
			
		||||
 | 
			
		||||
		BasicConstraintsValid: true,
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	hosts := strings.Split(host, ",")
 | 
			
		||||
 | 
			
		||||
	for _, h := range hosts {
 | 
			
		||||
 | 
			
		||||
		if ip := net.ParseIP(h); ip != nil {
 | 
			
		||||
 | 
			
		||||
			template.IPAddresses = append(template.IPAddresses, ip)
 | 
			
		||||
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			template.DNSNames = append(template.DNSNames, h)
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if isCA {
 | 
			
		||||
 | 
			
		||||
		template.IsCA = true
 | 
			
		||||
 | 
			
		||||
		template.KeyUsage |= x509.KeyUsageCertSign
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to create certificate: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	certOut, err := os.Create(CrtFile)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to open cert.pem for writing: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to write data to cert.pem: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := certOut.Close(); err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Error closing cert.pem: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Println("Finished creating: ", CrtFile)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	keyOut, err := os.OpenFile(KeyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to open key.pem for writing: %v", err)
 | 
			
		||||
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Unable to marshal private key: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Failed to write data to key.pem: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := keyOut.Close(); err != nil {
 | 
			
		||||
 | 
			
		||||
		log.Fatalf("Error closing key.pem: %v", err)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Println("Finished creating: ", KeyFile)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								zangtumb.go
								
								
								
								
							
							
						
						
									
										11
									
								
								zangtumb.go
								
								
								
								
							| 
						 | 
				
			
			@ -49,12 +49,19 @@ func init() {
 | 
			
		|||
		log.Println("WARNING: NOT Using TLS")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ZMakecert()
 | 
			
		||||
 | 
			
		||||
	log.Println("Ready to start the server.")
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
 | 
			
		||||
	if err := smtpd.ListenAndServe(ListenAddr, mailHandler, AppName, ServerName, ZangSmtpServer); err != nil {
 | 
			
		||||
	log.Println("Starting the server....")
 | 
			
		||||
 | 
			
		||||
	defer log.Println("Shutting down the server")
 | 
			
		||||
 | 
			
		||||
	if err := smtpd.ListenAndServe(ListenAddr, mailHandler, handlerRcpt, AppName, ServerName, ZangSmtpServer); err != nil {
 | 
			
		||||
		log.Panicln("Ops. Something went wrong: ", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue