Added docs on using with url-auth.
[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 (eval-when-compile (require 'cl))
55 (eval-when-compile (require 'netrc))
56
57 (defgroup auth-source nil
58   "Authentication sources."
59   :version "23.1" ;; No Gnus
60   :group 'gnus)
61
62 (defcustom auth-source-protocols '((imap "imap" "imaps" "143" "993")
63                                    (pop3 "pop3" "pop" "pop3s" "110" "995")
64                                    (ssh  "ssh" "22")
65                                    (sftp "sftp" "115")
66                                    (smtp "smtp" "25"))
67   "List of authentication protocols and their names"
68
69   :group 'auth-source
70   :version "23.1" ;; No Gnus
71   :type '(repeat :tag "Authentication Protocols"
72                  (cons :tag "Protocol Entry"
73                        (symbol :tag "Protocol")
74                        (repeat :tag "Names"
75                                (string :tag "Name")))))
76
77 ;;; generate all the protocols in a format Customize can use
78 (defconst auth-source-protocols-customize
79   (mapcar (lambda (a)
80             (let ((p (car-safe a)))
81               (list 'const 
82                     :tag (upcase (symbol-name p))
83                     p)))
84           auth-source-protocols))
85
86 ;;; this default will be changed to ~/.authinfo.gpg
87 (defcustom auth-sources '((:source "~/.authinfo.enc" :host t :protocol t))
88   "List of authentication sources.
89
90 Each entry is the authentication type with optional properties."
91   :group 'auth-source
92   :version "23.1" ;; No Gnus
93   :type `(repeat :tag "Authentication Sources"
94                  (list :tag "Source definition"
95                        (const :format "" :value :source)
96                        (string :tag "Authentication Source")
97                        (const :format "" :value :host)
98                        (choice :tag "Host (machine) choice"
99                                (const :tag "Any" t)
100                                (regexp :tag "Host (machine) regular expression (TODO)")
101                                (const :tag "Fallback" nil))
102                        (const :format "" :value :protocol)
103                        (choice :tag "Protocol"
104                                (const :tag "Any" t)
105                                (const :tag "Fallback" nil)
106                                ,@auth-source-protocols-customize))))
107
108 ;; temp for debugging
109 ;; (unintern 'auth-source-protocols)
110 ;; (unintern 'auth-sources)
111 ;; (customize-variable 'auth-sources)
112 ;; (setq auth-sources nil)
113 ;; (format "%S" auth-sources)
114 ;; (customize-variable 'auth-source-protocols)
115 ;; (setq auth-source-protocols nil)
116 ;; (format "%S" auth-source-protocols)
117 ;; (auth-source-pick "a" 'imap)
118 ;; (auth-source-user-or-password "login" "imap.myhost.com" 'imap)
119 ;; (auth-source-user-or-password "password" "imap.myhost.com" 'imap)
120 ;; (auth-source-user-or-password-imap "login" "imap.myhost.com")
121 ;; (auth-source-user-or-password-imap "password" "imap.myhost.com")
122 ;; (auth-source-protocol-defaults 'imap)
123
124 (defun auth-source-pick (host protocol &optional fallback)
125   "Parse `auth-sources' for HOST, and PROTOCOL matches.
126
127 Returns fallback choices (where PROTOCOL or HOST are nil) with FALLBACK t."
128   (interactive "sHost: \nsProtocol: \n") ;for testing
129   (let (choices)
130     (dolist (choice auth-sources)
131       (let ((h (plist-get choice :host))
132             (p (plist-get choice :protocol)))
133         (when (and
134                (or (equal t h)
135                    (and (stringp h) (string-match h host))
136                    (and fallback (equal h nil)))
137                (or (equal t p)
138                    (and (symbolp p) (equal p protocol))
139                    (and fallback (equal p nil))))
140           (push choice choices))))
141     (if choices
142         choices
143       (unless fallback
144         (auth-source-pick host protocol t)))))
145
146 (defun auth-source-user-or-password (mode host protocol)
147   "Find user or password (from the string MODE) matching HOST and PROTOCOL."
148 ;;; (debug mode host protocol)
149   (let (found)
150     (dolist (choice (auth-source-pick host protocol))
151       (setq found (netrc-machine-user-or-password 
152                    mode
153                    (plist-get choice :source)
154                    (list host)
155                    (list (format "%s" protocol))
156                    (auth-source-protocol-defaults protocol)))
157       (when found
158         (return found)))))
159
160 (defun auth-source-protocol-defaults (protocol)
161   "Return a list of default ports and names for PROTOCOL."
162   (cdr-safe (assoc protocol auth-source-protocols)))
163
164 (defun auth-source-user-or-password-imap (mode host)
165   (auth-source-user-or-password mode host 'imap))
166
167 (defun auth-source-user-or-password-pop3 (mode host)
168   (auth-source-user-or-password mode host 'pop3))
169
170 (defun auth-source-user-or-password-ssh (mode host)
171   (auth-source-user-or-password mode host 'ssh))
172
173 (defun auth-source-user-or-password-sftp (mode host)
174   (auth-source-user-or-password mode host 'sftp))
175
176 (defun auth-source-user-or-password-smtp (mode host)
177   (auth-source-user-or-password mode host 'smtp))
178
179 (provide 'auth-source)
180
181 ;; arch-tag: ff1afe78-06e9-42c2-b693-e9f922cbe4ab
182 ;;; auth-source.el ends here