login-validator: Save shadow file by IP
This commit is contained in:
parent
59abc217d1
commit
26c162f319
@ -169,5 +169,5 @@ func (l loginChecker) registerUser(username, remoteAddr string, ent ARPEntry) (n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l loginChecker) lateLoginAction(username, remoteAddr string, mac ARPEntry, ip net.IP) error {
|
func (l loginChecker) lateLoginAction(username, remoteAddr string, mac ARPEntry, ip net.IP) error {
|
||||||
return RegisterUserMAC(mac, ip, username)
|
return RegisterUserMAC(mac, ip, username, remoteAddr)
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,27 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cavaliergopher/cpio"
|
"github.com/cavaliergopher/cpio"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func copy_challenge(fd io.Writer) error {
|
||||||
|
fdchal, err := os.Open(path.Join(tftpDir, "challenge-initrd.img"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fdchal.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(fd, fdchal)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func passwd(w http.ResponseWriter, r *http.Request) {
|
func passwd(w http.ResponseWriter, r *http.Request) {
|
||||||
if addr := r.Header.Get("X-Forwarded-For"); addr != "" {
|
if addr := r.Header.Get("X-Forwarded-For"); addr != "" {
|
||||||
r.RemoteAddr = addr
|
r.RemoteAddr = addr
|
||||||
@ -45,7 +56,10 @@ func passwd(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
// Save the file
|
// Save the file
|
||||||
fd, err := os.Create(path.Join(tftpDir, "shadows", fmt.Sprintf("%s.img", initrd_name(r.RemoteAddr))))
|
initrd := initrd_name(r.RemoteAddr)
|
||||||
|
os.MkdirAll(path.Join(tftpDir, "shadows", initrd), 0755)
|
||||||
|
|
||||||
|
fd, err := os.Create(path.Join(tftpDir, "shadows", initrd, "challenge-initrd.img"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error when creating shadow file from", r.RemoteAddr, err.Error())
|
log.Println("Error when creating shadow file from", r.RemoteAddr, err.Error())
|
||||||
http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError)
|
http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError)
|
||||||
@ -53,25 +67,32 @@ func passwd(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
defer fd.Close()
|
defer fd.Close()
|
||||||
|
|
||||||
|
fd2, err := os.Create(path.Join(tftpDir, "shadows", initrd, "shadow"))
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error when creating shadow file from", r.RemoteAddr, err.Error())
|
||||||
|
http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fd2.Close()
|
||||||
|
|
||||||
// Copy the original challenge
|
// Copy the original challenge
|
||||||
fdchal, err := os.Open(path.Join(tftpDir, "challenge-initrd.img"))
|
err = copy_challenge(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(r.RemoteAddr, "Error when opening original challenge initramfs:", err.Error())
|
log.Println(r.RemoteAddr, "Error when opening original challenge initramfs:", err.Error())
|
||||||
http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError)
|
http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer fdchal.Close()
|
|
||||||
|
|
||||||
io.Copy(fd, fdchal)
|
|
||||||
|
|
||||||
// Append the new cpio archive
|
// Append the new cpio archive
|
||||||
zw := gzip.NewWriter(fd)
|
wfd := io.MultiWriter(fd, fd2)
|
||||||
|
zw := gzip.NewWriter(wfd)
|
||||||
wcpio := cpio.NewWriter(zw)
|
wcpio := cpio.NewWriter(zw)
|
||||||
|
|
||||||
hdr := &cpio.Header{
|
hdr := &cpio.Header{
|
||||||
Name: "etc/shadow",
|
Name: "etc/shadow_",
|
||||||
Mode: 0640,
|
Mode: 0640,
|
||||||
Size: header.Size,
|
ModTime: time.Now(),
|
||||||
|
Size: header.Size,
|
||||||
}
|
}
|
||||||
if err := wcpio.WriteHeader(hdr); err != nil {
|
if err := wcpio.WriteHeader(hdr); err != nil {
|
||||||
log.Println("Error when writing cpio header from", r.RemoteAddr, err.Error())
|
log.Println("Error when writing cpio header from", r.RemoteAddr, err.Error())
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -16,25 +17,22 @@ const pxeUserTplPath = "pxelinux.cfg/tpl"
|
|||||||
const ipxeUserTplPath = "pxelinux.cfg/tpl.ipxe"
|
const ipxeUserTplPath = "pxelinux.cfg/tpl.ipxe"
|
||||||
const pxeUserPath = "pxelinux.cfg"
|
const pxeUserPath = "pxelinux.cfg"
|
||||||
|
|
||||||
func RegisterUserMAC(ent ARPEntry, ip net.IP, username string) error {
|
func RegisterUserMAC(ent ARPEntry, ip net.IP, username, remoteAddr string) error {
|
||||||
if err := registerUser(ipxeUserTplPath, fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x.ipxe", ent.HWAddress[0], ent.HWAddress[1], ent.HWAddress[2], ent.HWAddress[3], ent.HWAddress[4], ent.HWAddress[5]), username, ip); err != nil {
|
if err := registerUser(ipxeUserTplPath, remoteAddr, fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x.ipxe", ent.HWAddress[0], ent.HWAddress[1], ent.HWAddress[2], ent.HWAddress[3], ent.HWAddress[4], ent.HWAddress[5]), username, ip); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
return registerUser(pxeUserTplPath, fmt.Sprintf("%02x-%02x-%02x-%02x-%02x-%02x-%02x", ent.HWType, ent.HWAddress[0], ent.HWAddress[1], ent.HWAddress[2], ent.HWAddress[3], ent.HWAddress[4], ent.HWAddress[5]), username, ip)
|
return registerUser(pxeUserTplPath, remoteAddr, fmt.Sprintf("%02x-%02x-%02x-%02x-%02x-%02x-%02x", ent.HWType, ent.HWAddress[0], ent.HWAddress[1], ent.HWAddress[2], ent.HWAddress[3], ent.HWAddress[4], ent.HWAddress[5]), username, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterUserIP(ip net.IP, username string) error {
|
|
||||||
return registerUser(pxeUserTplPath, fmt.Sprintf("%02X%02X%02X%02X", ip.To4()[0], ip.To4()[1], ip.To4()[2], ip.To4()[3]), username, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initrd_name(remote string) string {
|
func initrd_name(remote string) string {
|
||||||
|
log.Println("initrd_name:", remote)
|
||||||
initrd := hmac.New(md5.New, []byte(loginSalt))
|
initrd := hmac.New(md5.New, []byte(loginSalt))
|
||||||
initrd.Write([]byte(remote))
|
initrd.Write([]byte(remote))
|
||||||
return fmt.Sprintf("%x", initrd.Sum(nil))
|
return fmt.Sprintf("%x", initrd.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerUser(tplPath string, filename string, username string, ip net.IP) error {
|
func registerUser(tplPath, remoteAddr string, filename string, username string, ip net.IP) error {
|
||||||
if pxeTplCnt, err := ioutil.ReadFile(path.Join(tftpDir, tplPath)); err != nil {
|
if pxeTplCnt, err := ioutil.ReadFile(path.Join(tftpDir, tplPath)); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if userfd, err := os.OpenFile(path.Join(tftpDir, pxeUserPath, filename), os.O_RDWR|os.O_CREATE, 0644); err != nil {
|
} else if userfd, err := os.OpenFile(path.Join(tftpDir, pxeUserPath, filename), os.O_RDWR|os.O_CREATE, 0644); err != nil {
|
||||||
@ -42,6 +40,24 @@ func registerUser(tplPath string, filename string, username string, ip net.IP) e
|
|||||||
} else {
|
} else {
|
||||||
defer userfd.Close()
|
defer userfd.Close()
|
||||||
|
|
||||||
|
initrd := initrd_name(remoteAddr)
|
||||||
|
|
||||||
|
err := os.MkdirAll(path.Join(tftpDir, "shadows", initrd), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := os.Create(path.Join(tftpDir, "shadows", initrd, "challenge-initrd.img"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
err = copy_challenge(fd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
pkey := hmac.New(sha512.New512_224, []byte(loginSalt))
|
pkey := hmac.New(sha512.New512_224, []byte(loginSalt))
|
||||||
pkey.Write([]byte(username))
|
pkey.Write([]byte(username))
|
||||||
|
|
||||||
@ -53,7 +69,7 @@ func registerUser(tplPath string, filename string, username string, ip net.IP) e
|
|||||||
return err
|
return err
|
||||||
} else if err := pxeTmpl.Execute(userfd, map[string]string{
|
} else if err := pxeTmpl.Execute(userfd, map[string]string{
|
||||||
"username": username,
|
"username": username,
|
||||||
"initrd": initrd_name(ip.String()),
|
"initrd": initrd,
|
||||||
"pkey": fmt.Sprintf("%x", pkey.Sum(nil)),
|
"pkey": fmt.Sprintf("%x", pkey.Sum(nil)),
|
||||||
"ip": ip.String(),
|
"ip": ip.String(),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
24
server.yml
24
server.yml
@ -143,6 +143,7 @@ services:
|
|||||||
- /srv/tftp:/srv/tftp:ro
|
- /srv/tftp:/srv/tftp:ro
|
||||||
- /var/lib/adlin/pxelinux.cfg:/srv/tftp/bios/pxelinux.cfg
|
- /var/lib/adlin/pxelinux.cfg:/srv/tftp/bios/pxelinux.cfg
|
||||||
- /var/lib/adlin/pxelinux.cfg:/srv/tftp/pxelinux.cfg
|
- /var/lib/adlin/pxelinux.cfg:/srv/tftp/pxelinux.cfg
|
||||||
|
- /var/lib/adlin/shadows:/srv/tftp/s
|
||||||
|
|
||||||
- name: arp-spoofer
|
- name: arp-spoofer
|
||||||
image: nemunaire/adlin-arp-spoofer:9cfd4b106e4a70281fad33fb36df1a189f846cb6
|
image: nemunaire/adlin-arp-spoofer:9cfd4b106e4a70281fad33fb36df1a189f846cb6
|
||||||
@ -159,6 +160,8 @@ services:
|
|||||||
- /etc/resolv.conf:/etc/resolv.conf:ro
|
- /etc/resolv.conf:/etc/resolv.conf:ro
|
||||||
- /var/lib/adlin/students.csv:/students.csv:ro
|
- /var/lib/adlin/students.csv:/students.csv:ro
|
||||||
- /var/lib/adlin/pxelinux.cfg:/var/tftp/pxelinux.cfg
|
- /var/lib/adlin/pxelinux.cfg:/var/tftp/pxelinux.cfg
|
||||||
|
- /var/lib/adlin/shadows:/var/tftp/shadows
|
||||||
|
- /srv/tftp/challenge-initrd.img:/var/tftp/challenge-initrd.img:ro
|
||||||
- /etc/ssl/certs:/etc/ssl/certs:ro
|
- /etc/ssl/certs:/etc/ssl/certs:ro
|
||||||
- /usr/share/ca-certificates:/usr/share/ca-certificates:ro
|
- /usr/share/ca-certificates:/usr/share/ca-certificates:ro
|
||||||
- name: nginx-login
|
- name: nginx-login
|
||||||
@ -276,6 +279,7 @@ files:
|
|||||||
- path: etc/init.d/011-copy-to-var
|
- path: etc/init.d/011-copy-to-var
|
||||||
contents: |
|
contents: |
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
mkdir -p /var/lib/adlin/shadows
|
||||||
cp -r /srv/tftp/pxelinux.cfg /var/lib/adlin/
|
cp -r /srv/tftp/pxelinux.cfg /var/lib/adlin/
|
||||||
touch /var/lib/adlin/dhcp/dhcpd.leases
|
touch /var/lib/adlin/dhcp/dhcpd.leases
|
||||||
|
|
||||||
@ -287,6 +291,17 @@ files:
|
|||||||
/usr/sbin/crond
|
/usr/sbin/crond
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
|
|
||||||
|
- path: etc/init.d/032-update-std-initrd
|
||||||
|
contents: |
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for IRD in /var/lib/adlin/shadows/*/challenge-initrd.img
|
||||||
|
do
|
||||||
|
cat "/srv/tftp/challenge-initrd.img" > "${IRD}"
|
||||||
|
[ -f "${IRD%/challenge-initrd.img}/shadow" ] && cat "${IRD%/challenge-initrd.img}/shadow" >> "${IRD}"
|
||||||
|
done
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
- path: etc/init.d/021-nameserver
|
- path: etc/init.d/021-nameserver
|
||||||
contents: |
|
contents: |
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
@ -539,6 +554,10 @@ files:
|
|||||||
proxy_pass http://localhost:8081;
|
proxy_pass http://localhost:8081;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
}
|
}
|
||||||
|
location /passwd {
|
||||||
|
proxy_pass http://localhost:8081;
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
}
|
||||||
location /logout {
|
location /logout {
|
||||||
proxy_pass http://localhost:8081;
|
proxy_pass http://localhost:8081;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
@ -844,6 +863,9 @@ files:
|
|||||||
- path: srv/tftp
|
- path: srv/tftp
|
||||||
directory: true
|
directory: true
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
|
- path: srv/tftp/s
|
||||||
|
directory: true
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
- path: srv/tftp/bios/ldlinux.c32
|
- path: srv/tftp/bios/ldlinux.c32
|
||||||
source: /usr/share/syslinux/ldlinux.c32
|
source: /usr/share/syslinux/ldlinux.c32
|
||||||
@ -892,7 +914,7 @@ files:
|
|||||||
source: /var/tftp/adlin/bzImage
|
source: /var/tftp/adlin/bzImage
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
- path: srv/tftp/login-initrd.img
|
- path: srv/tftp/login-initrd.img
|
||||||
source: tftp/login-initrd.img
|
source: login-initrd.img
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
- path: srv/tftp/challenge-initrd.img
|
- path: srv/tftp/challenge-initrd.img
|
||||||
source: challenge-initrd.img
|
source: challenge-initrd.img
|
||||||
|
@ -20,7 +20,7 @@ menu title Welcome {{ .username }} to the EPITA ADvanced LINux administration co
|
|||||||
LABEL challenge
|
LABEL challenge
|
||||||
MENU LABEL ^Enter Challenge
|
MENU LABEL ^Enter Challenge
|
||||||
KERNEL ../bzImage
|
KERNEL ../bzImage
|
||||||
INITRD ../s/{{ .initrd }}.img
|
INITRD ../s/{{ .initrd }}/challenge-initrd.img
|
||||||
APPEND console=tty0 adlin.login={{ .username }} adlin.key={{ .pkey }} adlin.ip={{ .ip }} quiet
|
APPEND console=tty0 adlin.login={{ .username }} adlin.key={{ .pkey }} adlin.ip={{ .ip }} quiet
|
||||||
text help
|
text help
|
||||||
You are currently identified as {{ .username }}.
|
You are currently identified as {{ .username }}.
|
||||||
|
@ -30,7 +30,7 @@ echo -n Kernel command line: ${}
|
|||||||
read cmdline || goto start
|
read cmdline || goto start
|
||||||
|
|
||||||
kernel tftp://${next-server}/bzImage ${cmdline} adlin.login={{ .username }} adlin.key={{ .pkey }} adlin.ip={{ .ip }}
|
kernel tftp://${next-server}/bzImage ${cmdline} adlin.login={{ .username }} adlin.key={{ .pkey }} adlin.ip={{ .ip }}
|
||||||
initrd tftp://${next-server}/s/{{ .initrd }}.img
|
initrd tftp://${next-server}/s/{{ .initrd }}/challenge-initrd.img
|
||||||
boot || goto failed
|
boot || goto failed
|
||||||
goto start
|
goto start
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user