/
server.go
123 lines (116 loc) · 3.03 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package cmd
import (
"crypto/rand"
"encoding/base32"
"fmt"
"log"
"net/http"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/mattkasun/sshlogin"
"golang.org/x/crypto/ssh"
)
var users map[string]string
func run(p int) {
users = make(map[string]string)
router := setupRouter()
router.Run(fmt.Sprintf("127.0.0.1:%d", p))
}
func setupRouter() *gin.Engine {
r := gin.Default()
store := cookie.NewStore([]byte("ThisSecretShouldBeChangedInProduction"))
store.Options(sessions.Options{MaxAge: 300, Secure: true, HttpOnly: true, SameSite: http.SameSiteStrictMode})
session := sessions.Sessions("sshlogin", store)
r.Use(session)
r.GET("/hello", func(c *gin.Context) {
c.String(200, randomString(14))
})
r.POST("/login", func(c *gin.Context) {
var login sshlogin.Login
if err := c.ShouldBindJSON(&login); err != nil {
log.Println("login ", err)
c.JSON(400, gin.H{"error": err.Error()})
return
}
fmt.Println(users)
pub, ok := users[login.User]
if !ok {
c.JSON(http.StatusBadRequest, gin.H{"error": "user not found"})
return
}
pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pub))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if err := pubKey.Verify([]byte(login.Message), &login.Sig); err != nil {
log.Println("login verify ", err)
c.JSON(401, gin.H{"error": err.Error()})
return
}
session := sessions.Default(c)
session.Set("loggedIn", true)
session.Set("user", login.User)
session.Save()
c.JSON(200, gin.H{"message": "Hello World"})
})
r.POST("/register", func(c *gin.Context) {
var reg sshlogin.Registation
if err := c.ShouldBindJSON(®); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
_, ok := users[reg.User]
if ok {
c.JSON(http.StatusBadRequest, gin.H{"error": "username is taken"})
return
}
users[reg.User] = reg.Key
c.String(http.StatusOK, "registration successfull")
})
restricted := r.Group("/pages", auth)
{
restricted.GET("/ip", func(c *gin.Context) {
c.String(http.StatusOK, c.Request.RemoteAddr)
})
restricted.POST("/lines", func(c *gin.Context) {
data := make(map[string]string)
if err := c.ShouldBindJSON(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, data)
})
}
return r
}
func auth(c *gin.Context) {
var empty interface{}
session := sessions.Default(c)
user := session.Get("user")
if user == empty {
c.String(http.StatusUnauthorized, "access denied")
c.Abort()
return
}
if _, ok := users[user.(string)]; !ok {
c.String(http.StatusUnauthorized, "access denied")
c.Abort()
return
}
loggedIn := session.Get("loggedIn")
if loggedIn != true {
c.String(http.StatusUnauthorized, "access denied")
c.Abort()
return
}
}
func randomString(n int) string {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
log.Fatal("randomString", err)
}
return base32.StdEncoding.EncodeToString(b)[:n]
}