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