(use-modules (srfi srfi-1) (srfi srfi-13) (ice-9 binary-ports) (ice-9 textual-ports) (ice-9 format) (ice-9 regex) (rnrs bytevectors)) (define *host-passwd-file* (getenv "FUDO_HOST_PASSWD_FILE")) (when (not *host-passwd-file*) (format #t (current-error-port "FUDO_HOST_PASSWD_FILE not set~%")) (exit 1)) (define *service-passwd-file* (getenv "FUDO_SERVICE_PASSWD_FILE")) (when (not *service-passwd-file*) (format #t (current-error-port "FUDO_SERVICE_PASSWD_FILE not set~%")) (exit 1)) (define host-regex "^host-([a-zA-Z][a-zA-Z0-9_-]+)$") (define service-regex "^service-([a-zA-Z][a-zA-Z0-9_-]+)$") (define (make-verifier passwd-file) (let ((passwds (load passwd-file))) (lambda (username passwd) (and (> (string-length passwd) 6) (equal? (assoc-ref passwds username) passwd))))) (define (make-authenticator host-verifier service-verifier) (lambda (username hostname password) (cond ((string-match host-regex username) (host-verifier (match:substring (string-match host-regex username) 1) password)) ((string-match service-regex username) (service-verifier (match:substring (string-match service-regex username) 1) password)) (else (begin (format #t "unrecognized username: ~s @ ~s~%" username hostname) nil))))) (define (make-handler handlers) (lambda (request) (let ((op (assoc-ref handlers (first request)))) (if op (apply op (cdr request)) #f)))) (define (auth-listener handler) (let ((in (current-input-port)) (out (current-output-port))) (while (not (eof-object? in)) (let ((size (bytevector-u16-ref (get-bytevector-n in 2) 0 (endianness big))) (response (make-bytevector 4 0))) (bytevector-u8-set! response 1 #x02) (if (handler (string-split (get-string-n in size) #\:)) (begin (bytevector-u8-set! response 3 #x01) (put-bytevector out response 0 4) (force-output out)) (begin (bytevector-u8-set! response 3 #x00) (put-bytevector out response 0 4) (force-output out))))))) (auth-listener (make-handler (list (cons "auth" (make-authenticator (make-verifier *host-passwd-file*) (make-verifier *service-passwd-file*))))))