6c53da191e1020477b52f99358fa88930566bed8
[gnus] / lisp / auth-source.el
1 ;;; auth-source.el --- authentication sources for Gnus and Emacs
2
3 ;; Copyright (C) 2008 Free Software Foundation, Inc.
4
5 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
6 ;; Keywords: news
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;; Commentary:
26
27 ;; This is the auth-source.el package.  It lets users tell Gnus how to
28 ;; authenticate in a single place.  Simplicity is the goal.  Instead
29 ;; of providing 5000 options, we'll stick to simple, easy to
30 ;; understand options.
31
32 ;; Easy setup:
33 ;; (require 'auth-source)
34 ;; (customize-variable 'auth-sources) ;; optional
35
36 ;; now, whatever sources you've defined for password have to be available
37
38 ;; if you want encrypted sources, which is strongly recommended, do
39 ;; (require 'epa-file)
40 ;; (epa-file-mode)
41
42 ;; before you put some data in ~/.authinfo.gpg (the default place)
43
44 ;;; For url-auth authentication (HTTP/HTTPS), you need to use:
45
46 ;;; machine yourmachine.com:80 port http login testuser password testpass
47
48 ;;; This will match any realm and authentication method (basic or
49 ;;; digest).  If you want finer controls, explore the url-auth source
50 ;;; code and variables.
51
52 ;;; Code:
53
54 (require 'gnus-util)
55
56 (eval-when-compile (require 'cl))
57 (eval-when-compile (require 'netrc))
58
59 (defgroup auth-source nil
60   "Authentication sources."
61   :version "23.1" ;; No Gnus
62   :group 'gnus)
63
64 (defcustom auth-source-protocols '((imap "imap" "imaps" "143" "993")
65                                    (pop3 "pop3" "pop" "pop3s" "110" "995")
66                                    (ssh  "ssh" "22")
67                                    (sftp "sftp" "115")
68                                    (smtp "smtp" "25"))
69   "List of authentication protocols and their names"
70
71   :group 'auth-source
72   :version "23.1" ;; No Gnus
73   :type '(repeat :tag "Authentication Protocols"
74                  (cons :tag "Protocol Entry"
75                        (symbol :tag "Protocol")
76                        (repeat :tag "Names"
77                                (string :tag "Name")))))
78
79 ;;; generate all the protocols in a format Customize can use
80 (defconst auth-source-protocols-customize
81   (mapcar (lambda (a)
82             (let ((p (car-safe a)))
83               (list 'const 
84                     :tag (upcase (symbol-name p))
85                     p)))
86           auth-source-protocols))
87
88 ;;; this default will be changed to ~/.authinfo.gpg
89 (defcustom auth-sources '((:source "~/.authinfo.enc" :host t :protocol t))
90   "List of authentication sources.
91
92 Each entry is the authentication type with optional properties."
93   :group 'auth-source
94   :version "23.1" ;; No Gnus
95   :type `(repeat :tag "Authentication Sources"
96                  (list :tag "Source definition"
97                        (const :format "" :value :source)
98                        (string :tag "Authentication Source")
99                        (const :format "" :value :host)
100                        (choice :tag "Host (machine) choice"
101                                (const :tag "Any" t)
102                                (regexp :tag "Host (machine) regular expression (TODO)")
103                                (const :tag "Fallback" nil))
104                        (const :format "" :value :protocol)
105                        (choice :tag "Protocol"
106                                (const :tag "Any" t)
107                                (const :tag "Fallback" nil)
108                                ,@auth-source-protocols-customize))))
109
110 ;; temp for debugging
111 ;; (unintern 'auth-source-protocols)
112 ;; (unintern 'auth-sources)
113 ;; (customize-variable 'auth-sources)
114 ;; (setq auth-sources nil)
115 ;; (format "%S" auth-sources)
116 ;; (customize-variable 'auth-source-protocols)
117 ;; (setq auth-source-protocols nil)
118 ;; (format "%S" auth-source-protocols)
119 ;; (auth-source-pick "a" 'imap)
120 ;; (auth-source-user-or-password "login" "imap.myhost.com" 'imap)
121 ;; (auth-source-user-or-password "password" "imap.myhost.com" 'imap)
122 ;; (auth-source-user-or-password-imap "login" "imap.myhost.com")
123 ;; (auth-source-user-or-password-imap "password" "imap.myhost.com")
124 ;; (auth-source-protocol-defaults 'imap)
125
126 (defun auth-source-pick (host protocol &optional fallback)
127   "Parse `auth-sources' for HOST, and PROTOCOL matches.
128
129 Returns fallback choices (where PROTOCOL or HOST are nil) with FALLBACK t."
130   (interactive "sHost: \nsProtocol: \n") ;for testing
131   (let (choices)
132     (dolist (choice auth-sources)
133       (let ((h (plist-get choice :host))
134             (p (plist-get choice :protocol)))
135         (when (and
136                (or (equal t h)
137                    (and (stringp h) (string-match h host))
138                    (and fallback (equal h nil)))
139                (or (equal t p)
140                    (and (symbolp p) (equal p protocol))
141                    (and fallback (equal p nil))))
142           (push choice choices))))
143     (if choices
144         choices
145       (unless fallback
146         (auth-source-pick host protocol t)))))
147
148 (defun auth-source-user-or-password (mode host protocol)
149   "Find user or password (from the string MODE) matching HOST and PROTOCOL."
150   (gnus-message 9 
151                 "auth-source-user-or-password: get %s for %s (%s)"
152                 mode host protocol)
153   (let (found)
154     (dolist (choice (auth-source-pick host protocol))
155       (setq found (netrc-machine-user-or-password 
156                    mode
157                    (plist-get choice :source)
158                    (list host)
159                    (list (format "%s" protocol))
160                    (auth-source-protocol-defaults protocol)))
161       (when found
162         (gnus-message 9 
163                       "auth-source-user-or-password: found %s=%s for %s (%s)"
164                       mode 
165                       ;; don't show the password
166                       (if (equal mode "password") "SECRET" found) 
167                       host protocol)
168         (return found)))))
169
170 (defun auth-source-protocol-defaults (protocol)
171   "Return a list of default ports and names for PROTOCOL."
172   (cdr-safe (assoc protocol auth-source-protocols)))
173
174 (defun auth-source-user-or-password-imap (mode host)
175   (auth-source-user-or-password mode host 'imap))
176
177 (defun auth-source-user-or-password-pop3 (mode host)
178   (auth-source-user-or-password mode host 'pop3))
179
180 (defun auth-source-user-or-password-ssh (mode host)
181   (auth-source-user-or-password mode host 'ssh))
182
183 (defun auth-source-user-or-password-sftp (mode host)
184   (auth-source-user-or-password mode host 'sftp))
185
186 (defun auth-source-user-or-password-smtp (mode host)
187   (auth-source-user-or-password mode host 'smtp))
188
189 (provide 'auth-source)
190
191 ;; arch-tag: ff1afe78-06e9-42c2-b693-e9f922cbe4ab
192 ;;; auth-source.el ends here