github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/cmd/geph-binder/tickets.go (about) 1 package main 2 3 import ( 4 "crypto/x509" 5 "encoding/base64" 6 "encoding/json" 7 "log" 8 "net/http" 9 "runtime" 10 "sort" 11 "strings" 12 "sync" 13 "time" 14 15 "github.com/cryptoballot/rsablind" 16 "github.com/geph-official/geph2/libs/bdclient" 17 "github.com/patrickmn/go-cache" 18 ) 19 20 func handleGetTicketKey(w http.ResponseWriter, r *http.Request) { 21 countUserAgent(r) 22 // check type 23 key, err := getTicketIdentity(r.FormValue("tier")) 24 if err != nil { 25 w.WriteHeader(http.StatusInternalServerError) 26 return 27 } 28 w.Write([]byte(base64.RawStdEncoding.EncodeToString(x509.MarshalPKCS1PublicKey(&key.PublicKey)))) 29 } 30 31 func handleGetTier(w http.ResponseWriter, r *http.Request) { 32 countUserAgent(r) 33 // first authenticate 34 _, expiry, _, err := verifyUser(r.FormValue("user"), r.FormValue("pwd")) 35 if err != nil { 36 log.Println("cannot verify user:", err.Error()) 37 w.WriteHeader(http.StatusInternalServerError) 38 return 39 } 40 if expiry.After(time.Now()) { 41 w.Write([]byte("paid")) 42 } else { 43 w.Write([]byte("free")) 44 } 45 } 46 47 var cpuSemaphore chan bool 48 49 func init() { 50 cpuSemaphore = make(chan bool, runtime.GOMAXPROCS(0)*2) 51 } 52 53 var limiterCache sync.Map 54 55 var goodIPCache = cache.New(time.Hour, time.Minute) 56 57 func handleGetTicket(w http.ResponseWriter, r *http.Request) { 58 countUserAgent(r) 59 // first authenticate 60 uid, expiry, paytx, err := verifyUser(r.FormValue("user"), r.FormValue("pwd")) 61 if err != nil { 62 log.Println("cannot verify user:", err.Error()) 63 w.WriteHeader(http.StatusInternalServerError) 64 return 65 } 66 if uid < 0 { 67 log.Println("cannot log in user:", r.FormValue("user")) 68 w.WriteHeader(http.StatusForbidden) 69 return 70 } 71 // ticketLimiter, _ := limiterCache.LoadOrStore(uid, rate.NewLimiter(rate.Every(time.Minute*4), 100)) 72 // if !ticketLimiter.(*rate.Limiter).Allow() { 73 // log.Println("*** VIOLATED LIMIT ", r.FormValue("user")) 74 // time.Sleep(time.Second * 10) 75 // w.WriteHeader(http.StatusTooManyRequests) 76 // return 77 // } 78 log.Println("verified", r.FormValue("user")) 79 //log.Println("get-ticket: verified user", r.FormValue("user"), "as expiry", expiry) 80 var tier string 81 if expiry.After(time.Now()) { 82 tier = "paid" 83 } else { 84 tier = "free" 85 } 86 blinded, err := base64.RawStdEncoding.DecodeString(r.FormValue("blinded")) 87 if err != nil { 88 w.WriteHeader(http.StatusBadRequest) 89 return 90 } 91 //log.Println("get-ticket: user", r.FormValue("user"), "sent us blinded of length", len(blinded)) 92 // get the key 93 key, err := getTicketIdentity(tier) 94 if err != nil { 95 w.WriteHeader(http.StatusInternalServerError) 96 return 97 } 98 // issue the ticket. TODO rate limit this 99 ticket, err := rsablind.BlindSign(key, blinded) 100 if err != nil { 101 panic(err) 102 } 103 var toWrite bdclient.TicketResp 104 toWrite.Tier = tier 105 toWrite.Ticket = ticket 106 toWrite.PaidExpiry = expiry 107 if paytx != nil { 108 for k, v := range paytx { 109 toWrite.Transactions = append(toWrite.Transactions, bdclient.PaymentTx{ 110 Amount: v, 111 Date: k, 112 }) 113 } 114 sort.Slice(toWrite.Transactions, func(i, j int) bool { 115 return toWrite.Transactions[i].Date.After(toWrite.Transactions[j].Date) 116 }) 117 } 118 b, err := json.Marshal(toWrite) 119 if err != nil { 120 panic(err) 121 } 122 w.Write([]byte(b)) 123 id := strings.Split(r.Header.Get("X-Forwarded-For"), ",")[0] 124 goodIPCache.SetDefault(id, uid) 125 } 126 127 func handleRedeemTicket(w http.ResponseWriter, r *http.Request) { 128 countUserAgent(r) 129 // check type 130 if tier := r.FormValue("tier"); tier != "free" && tier != "paid" { 131 log.Println("bad tier:", tier) 132 w.WriteHeader(http.StatusBadRequest) 133 return 134 } 135 // obtain key 136 key, err := getTicketIdentity(r.FormValue("tier")) 137 if err != nil { 138 w.WriteHeader(http.StatusInternalServerError) 139 return 140 } 141 // obtain values 142 ubmsg, err := base64.RawStdEncoding.DecodeString(r.FormValue("ubmsg")) 143 if err != nil { 144 w.WriteHeader(http.StatusBadRequest) 145 return 146 } 147 ubsig, err := base64.RawStdEncoding.DecodeString(r.FormValue("ubsig")) 148 if err != nil { 149 w.WriteHeader(http.StatusBadRequest) 150 return 151 } 152 // verify 153 if err := rsablind.VerifyBlindSignature(&key.PublicKey, ubmsg, ubsig); err != nil { 154 w.WriteHeader(http.StatusForbidden) 155 return 156 } 157 return 158 }