package main
import (
"crypto"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"flag"
"fmt"
"log"
"net/http"
"os"
"strconv"
"strings"
)
func main() {
log.SetOutput(os.Stdout)
port := flag.Int("p", 21017, "port")
host := flag.String("host", "0.0.0.0", "Bind TCP Address")
flag.Parse()
log.Println("*************************************************************")
log.Printf("** %-55s**", "JetBrains License Server")
log.Printf("** %-55s**", "Please support genuine!!!")
log.Printf("** Listen on %-45s**", fmt.Sprintf("%s:%d...", *host, *port))
addr := fmt.Sprintf("%s:%d", *host, *port)
if strings.Contains(addr, "0.0.0.0") {
addr = strings.Replace(addr, "0.0.0.0", "", 1)
*host = strings.Replace(*host, "0.0.0.0", "127.0.0.1", 1)
}
log.Printf("** You can use %-43s**", fmt.Sprintf("http://%s:%d as license server", *host, *port))
log.Println("*************************************************************")
routerBinding()
err := http.ListenAndServe(addr, http.DefaultServeMux)
if err != nil {
log.Fatalln(err)
}
}
func urlMatcher(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.URL.Path = strings.ToLower(r.URL.Path)
h.ServeHTTP(w, r)
})
}
func routerBinding() {
mux := http.NewServeMux()
http.Handle("/", urlMatcher(mux))
mux.HandleFunc("/", index)
mux.HandleFunc("/rpc/ping.action", ping)
mux.HandleFunc("/rpc/obtainticket.action", obtainTicket)
}
func index(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("JetBrains License Server is started!"))
}
func ping(w http.ResponseWriter, r *http.Request) {
log.Println(r.URL)
salt := r.URL.Query().Get("salt")
xmlResponse := "OK" + salt + ""
xmlSignature, _ := signature(xmlResponse)
w.Header().Add("Content-Type", "text/xml")
w.Write([]byte("\n" + xmlResponse))
}
func obtainTicket(w http.ResponseWriter, r *http.Request) {
// log.Println(r.URL)
salt := r.URL.Query().Get("salt")
username := r.URL.Query().Get("userName")
if salt == "" || username == "" {
w.WriteHeader(http.StatusForbidden)
return
}
prolongationPeriod := 607875500
xmlResponse := "" + strconv.Itoa(prolongationPeriod) + "OK" + salt + "1licensee=" + username + "\tlicenseType=0\t"
xmlSignature, _ := signature(xmlResponse)
w.Header().Add("Content-Type", "text/xml")
w.Write([]byte("\n" + xmlResponse))
}
var privateKey = []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALecq3BwAI4YJZwhJ+snnDFj3lF3DMqNPorV6y5ZKXCiCMqj8OeOmxk4YZW9aaV9
ckl/zlAOI0mpB3pDT+Xlj2sCAwEAAQJAW6/aVD05qbsZHMvZuS2Aa5FpNNj0BDlf38hOtkhDzz/h
kYb+EBYLLvldhgsD0OvRNy8yhz7EjaUqLCB0juIN4QIhAOeCQp+NXxfBmfdG/S+XbRUAdv8iHBl+
F6O2wr5fA2jzAiEAywlDfGIl6acnakPrmJE0IL8qvuO3FtsHBrpkUuOnXakCIQCqdr+XvADI/UTh
TuQepuErFayJMBSAsNe3NFsw0cUxAQIgGA5n7ZPfdBi3BdM4VeJWb87WrLlkVxPqeDSbcGrCyMkC
IFSs5JyXvFTreWt7IQjDssrKDRIPmALdNjvfETwlNJyY
-----END RSA PRIVATE KEY-----
`)
func signature(message string) (string, error) {
// key, err := ioutil.ReadFile("rsa.key")
// if err != nil {
// return "", err
// }
// pem, _ := pem.Decode(key)
pem, _ := pem.Decode([]byte(privateKey))
rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(pem.Bytes)
hashedMessage := md5.Sum([]byte(message))
signature, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey, crypto.MD5, hashedMessage[:])
if err != nil {
return "", err
}
hexSignature := hex.EncodeToString(signature)
return hexSignature, nil
}