auth.scm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. ;;; auth.scm -- API for SSH user authentication.
  2. ;; Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com>
  3. ;;
  4. ;; This file is a part of Guile-SSH.
  5. ;;
  6. ;; Guile-SSH is free software: you can redistribute it and/or
  7. ;; modify it under the terms of the GNU General Public License as
  8. ;; published by the Free Software Foundation, either version 3 of the
  9. ;; License, or (at your option) any later version.
  10. ;;
  11. ;; Guile-SSH is distributed in the hope that it will be useful, but
  12. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;; General Public License for more details.
  15. ;;
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with Guile-SSH. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; This module contains API that is used for SSH user authentication.
  20. ;;
  21. ;; These methods are exported:
  22. ;;
  23. ;; userauth-public-key!
  24. ;; userauth-public-key/auto!
  25. ;; userauth-public-key/try
  26. ;; userauth-agent!
  27. ;; userauth-password!
  28. ;; userauth-none!
  29. ;; userauth-get-list
  30. ;;; Code:
  31. (define-module (ssh auth)
  32. #:use-module (ice-9 popen)
  33. #:use-module (ice-9 rdelim)
  34. #:use-module (ice-9 regex)
  35. #:use-module (ssh log)
  36. #:use-module (ssh session)
  37. #:export (userauth-public-key!
  38. userauth-public-key/auto!
  39. userauth-public-key/try
  40. userauth-agent!
  41. userauth-password!
  42. userauth-none!
  43. userauth-get-list
  44. openssh-agent-start
  45. openssh-agent-info
  46. openssh-agent-setenv))
  47. ;;;
  48. (define %ssh-auth-sock-regexp
  49. (make-regexp "SSH_AUTH_SOCK=(.*); export SSH_AUTH_SOCK;"))
  50. (define %ssh-agent-pid-regexp
  51. (make-regexp "SSH_AGENT_PID=(.*); export SSH_AGENT_PID;"))
  52. (define (openssh-agent-start)
  53. "Start an OpenSSH agent. Return a list with SSH agent information."
  54. (let ((p (open-input-pipe "ssh-agent -s")))
  55. (let ((ssh-auth-sock-data (read-line p))
  56. (ssh-agent-pid-data (read-line p)))
  57. `((SSH_AUTH_SOCK
  58. . ,(let ((match (regexp-exec %ssh-auth-sock-regexp
  59. ssh-auth-sock-data)))
  60. (match:substring match 1)))
  61. (SSH_AGENT_PID
  62. . ,(let ((match (regexp-exec %ssh-agent-pid-regexp
  63. ssh-agent-pid-data)))
  64. (match:substring match 1)))))))
  65. ;;;
  66. (define %ssh-agent-dir-regexp
  67. (make-regexp "ssh-[0-9A-Za-z]+$"))
  68. (define* (openssh-agent-info #:optional (user (getenv "USER")))
  69. "Get OpenSSH agent information for a given USER as a list."
  70. (define (owned-by-user? file-name uid)
  71. (= (stat:uid (stat file-name)) uid))
  72. (define (user->uid user)
  73. (passwd:uid (getpwnam user)))
  74. (define (readdir-3rd dir-name)
  75. (let ((stream (opendir dir-name)))
  76. (readdir stream)
  77. (readdir stream)
  78. (let ((file (readdir stream)))
  79. (closedir stream)
  80. file)))
  81. (define (agent-socket->pid agent-socket)
  82. (cdr (string-split agent-socket #\.)))
  83. (let ((dir (opendir "/tmp"))
  84. (uid (user->uid user)))
  85. (let loop ((entry (readdir dir))
  86. (info '()))
  87. (if (eof-object? entry)
  88. info
  89. (let ((file-name (string-append "/tmp/" entry)))
  90. (if (and (regexp-exec %ssh-agent-dir-regexp entry)
  91. (owned-by-user? file-name uid))
  92. (let ((agent-socket (readdir-3rd file-name)))
  93. (loop (readdir dir)
  94. (cons `(,(string-append file-name "/" agent-socket)
  95. . ,(agent-socket->pid agent-socket))
  96. info)))
  97. (loop (readdir dir) info)))))))
  98. ;;;
  99. (define (openssh-agent-setenv)
  100. "Setup openssh agent environment variables for the current user."
  101. (setenv "SSH_AUTH_SOCK" (caar (openssh-agent-info))))
  102. ;;;
  103. (load-extension "libguile-ssh" "init_auth_func")
  104. ;;; auth.scm ends here.