summaryrefslogtreecommitdiffstats
path: root/challenge
diff options
context:
space:
mode:
Diffstat (limited to 'challenge')
-rw-r--r--challenge/c36.go186
1 files changed, 184 insertions, 2 deletions
diff --git a/challenge/c36.go b/challenge/c36.go
index dc4456b..80c231a 100644
--- a/challenge/c36.go
+++ b/challenge/c36.go
@@ -6,6 +6,7 @@ package challenge
import (
"bufio"
"fmt"
+ "math/big"
"net"
"os"
@@ -49,6 +50,65 @@ func C36(args []string) {
}
return nil
}
+ // Login user on the server.
+ serverLoginUser := func(server *lib.SRPServer, info []string,
+ conn net.Conn) error {
+ if len(info) != 2 {
+ return fmt.Errorf("login user: info valid")
+ }
+ ident := info[0]
+ user, err := server.GetUser(ident)
+ if err != nil {
+ return fmt.Errorf("get user: %v", err)
+ }
+ if user.LoggedIn() {
+ return fmt.Errorf("user already has a session open")
+ }
+ clientPub := new(big.Int).SetBytes(lib.HexStrToBytes(info[1]))
+ if clientPub.Cmp(big.NewInt(0)) == 0 {
+ return fmt.Errorf("user public key invalid")
+ }
+
+ user.EphemeralKeyGen() // Generate server pub key for user.
+ serverPub, err := user.EphemeralKeyPub()
+ if err != nil {
+ return fmt.Errorf("server pub key: %v", err)
+ }
+
+ // Make ACK packet
+ packet := fmt.Sprintf("%s+%s", lib.BytesToHexStr(user.Salt()),
+ lib.BytesToHexStr(serverPub.Bytes()))
+
+ // Send packet to client.
+ _, err = fmt.Fprintf(conn, "%s\n", packet)
+ if err != nil {
+ return fmt.Errorf("sending packet to client: %v", err)
+ }
+
+ // Compute session key.
+ err = user.SetScramblingParam(clientPub)
+ if err != nil {
+ return fmt.Errorf("setting scrambling param: %v", err)
+ }
+ err = user.ComputeSessionKey(clientPub)
+ if err != nil {
+ return fmt.Errorf("computing session key: %v", err)
+ }
+
+ // Wait and try to read hmac from client.
+ cpacket, err := bufio.NewReader(conn).ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("hmac recv: %v", err)
+ }
+ hmac := []byte(cpacket[:len(cpacket)-1])
+ if !user.SessionKeyMacVerify(hmac) {
+ return fmt.Errorf("hmac verification: %v", hmac)
+ }
+ // Login user.
+ user.LogIn()
+
+ return nil
+ }
// Handle connection from a client.
serverHandleConn := func(server *lib.SRPServer, conn net.Conn) {
defer conn.Close()
@@ -81,6 +141,14 @@ func C36(args []string) {
fmt.Fprintf(conn, "OK\n")
}
return
+ case parts[0] == "login":
+ err = serverLoginUser(server, parts[1:], conn)
+ if err != nil {
+ fmt.Fprintf(conn, "%v\n", err)
+ } else {
+ fmt.Fprintf(conn, "OK\n")
+ }
+ return
default:
fmt.Fprintf(conn, "invalid action")
return
@@ -162,13 +230,118 @@ func C36(args []string) {
}
return nil
}
+ // Login user into the server.
+ clientLoginUser := func(client *lib.SRPClient, ident string) error {
+ n := lib.StripSpaceChars(
+ `ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024
+ e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd
+ 3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec
+ 6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f
+ 24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361
+ c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552
+ bb9ed529077096966d670c354e4abc9804f1746c08ca237327fff
+ fffffffffffff`)
+ g := "2"
+ k := "3"
+
+ // Prompt for password.
+ fmt.Printf("password> ")
+ pass, err := bufio.NewReader(os.Stdin).ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("unable to read password: %v", err)
+ }
+ pass = pass[:len(pass)-1]
+
+ // Create session for user.
+ client.Session, err = lib.NewSRPClientSession(n, g, k, ident)
+ if err != nil {
+ return fmt.Errorf("unable to create session: %v", err)
+ }
+
+ // Get session pub key.
+ pub, err := client.Session.EphemeralKeyPub()
+ if err != nil {
+ return fmt.Errorf("unable to get pub key: %v", err)
+ }
+
+ // Make SRP login packet.
+ packet := fmt.Sprintf("%s+%s+%s", "login",
+ ident, lib.BytesToHexStr(pub.Bytes()))
+
+ // Try to connect to server.
+ conn, err := net.Dial("tcp", fmt.Sprintf(":%d", port))
+ if err != nil {
+ return fmt.Errorf("unable connect to server: %v", err)
+ }
+ defer conn.Close()
+
+ // Send login packet to server.
+ _, err = fmt.Fprintf(conn, "%s\n", packet)
+ if err != nil {
+ return fmt.Errorf("unable communicate with server: %v", err)
+ }
+
+ // Wait and try to get registration ACK from server.
+ spacket, err := bufio.NewReader(conn).ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("server did not respond: %v", err)
+ }
+ // Remove newline character.
+ spacket = spacket[:len(spacket)-1]
+
+ if !lib.StrHas(spacket, "+") {
+ return fmt.Errorf("pub exchange: %s", spacket)
+ }
+ parts := lib.StrSplitAt('+', spacket)
+ if len(parts) < 2 {
+ return fmt.Errorf("server login response invalid")
+ }
+ salt := lib.HexStrToBytes(parts[0])
+ serverPub := new(big.Int).SetBytes(lib.HexStrToBytes(parts[1]))
+
+ // Compute session key.
+ err = client.Session.SetScramblingParam(serverPub)
+ if err != nil {
+ return fmt.Errorf("setting scrambling param: %v", err)
+ }
+ err = client.Session.ComputeSessionKey(salt, pass, serverPub)
+ if err != nil {
+ return fmt.Errorf("computing session key: %v", err)
+ }
+
+ // Compute session key hmac
+ hmac, err := client.Session.SessionKeyMac(salt)
+ if err != nil {
+ return fmt.Errorf("sesion key hmac: %v", err)
+ }
+
+ // Send hmac to server.
+ _, err = fmt.Fprintf(conn, "%s\n", hmac)
+ if err != nil {
+ return fmt.Errorf("sending hmac: %v", err)
+ }
+
+ // Wait and try to get registration ACK from server.
+ spacket, err = bufio.NewReader(conn).ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("server did not respond: %v", err)
+ }
+ // Remove newline character.
+ spacket = spacket[:len(spacket)-1]
+ if spacket != "OK" {
+ return fmt.Errorf("login failed: %s", spacket)
+ }
+ // Login user.
+ client.LogIn()
+ return nil
+ }
// Start SRP client.
clientSpawn := func() {
client := new(lib.SRPClient)
// Enter repl.
for {
// Read message from stdin.
- fmt.Printf("> ")
+ fmt.Printf("%s> ", client.Ident())
msg, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
fmt.Printf("read error: %v\n", err)
@@ -179,13 +352,22 @@ func C36(args []string) {
msg_parts := lib.StrSplitAt(' ', msg)
switch {
- case msg_parts[0] == "register" && len(msg_parts) == 2:
+ case !client.LoggedIn() && msg_parts[0] == "register" &&
+ len(msg_parts) == 2:
err := clientRegisterUser(client, msg_parts[1])
if err != nil {
fmt.Printf("Registration failed: %v\n", err)
} else {
fmt.Printf("Registered!\n")
}
+ case !client.LoggedIn() && msg_parts[0] == "login" &&
+ len(msg_parts) == 2:
+ err := clientLoginUser(client, msg_parts[1])
+ if err != nil {
+ fmt.Printf("Login failed: %v\n", err)
+ } else {
+ fmt.Printf("Logged in!\n")
+ }
}
}
}