aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/sql.el
diff options
context:
space:
mode:
authorMichael R. Mauger2019-02-18 23:15:54 -0500
committerMichael R. Mauger2019-02-18 23:15:54 -0500
commit1a6bcc91e3e468e5a6d3e0b121bb675b576d3362 (patch)
treeca325907ed02edcd6a463b5f5e5482bbc6f81ab9 /lisp/progmodes/sql.el
parented1e805af7d4892e7354e8c9e2246d5017d4ff52 (diff)
downloademacs-wallet.tar.gz
emacs-wallet.zip
* lisp/progmodes/sql.el: Added password wallet usingwallet
`auth-source' package. (sql-auth-source-search-wallet): New function. (sql-password-wallet): New variable. (sql-password-search-wallet-function): New variable. (sql-get-login): Handle password wallet search. (sql-product-interactive): Handle password function. * test/lisp/progmodes/sql-test.el: Test wallet changes. (sql-test-login-params): New test variable. (with-sql-test-connect-harness): New macro to wrap test configuration around calls to `sql-connect'. (sql-test-connect, sql-test-connect-password-func) (sql-test-connect-wallet-server-database) (sql-test-connect-wallet-database) (sql-test-connect-wallet-server): New ERT tests. * etc/NEWS: Updated SQL Mode descriptions.
Diffstat (limited to 'lisp/progmodes/sql.el')
-rw-r--r--lisp/progmodes/sql.el151
1 files changed, 150 insertions, 1 deletions
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 2df62585a0d..c72070b8923 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -748,6 +748,126 @@ The package must be available to be loaded and activated."
748 (when (sql-is-indent-available) 748 (when (sql-is-indent-available)
749 (sqlind-minor-mode (if sql-use-indent-support +1 -1)))) 749 (sqlind-minor-mode (if sql-use-indent-support +1 -1))))
750 750
751;; Secure Password wallet
752
753(require 'auth-source)
754
755(defun sql-auth-source-search-wallet (wallet product user server database port)
756 "Read auth source WALLET to locate the USER secret.
757Sets `auth-sources' to WALLET and uses `auth-source-search' to locate the entry.
758The DATABASE and SERVER are concatenated with a slash between them as the
759host key."
760 (let* ((auth-sources wallet)
761 host
762 secret h-secret sd-secret)
763
764 ;; product
765 (setq product (symbol-name product))
766
767 ;; user
768 (setq user (unless (string-empty-p user) user))
769
770 ;; port
771 (setq port
772 (when (and port (numberp port) (not (zerop port)))
773 (number-to-string port)))
774
775 ;; server
776 (setq server (unless (string-empty-p server) server))
777
778 ;; database
779 (setq database (unless (string-empty-p database) database))
780
781 ;; host
782 (setq host (if server
783 (if database
784 (concat server "/" database)
785 server)
786 database))
787
788 ;; Perform search
789 (dolist (s (auth-source-search :max 1000))
790 (when (and
791 ;; Is PRODUCT specified, in the enty, and they are equal
792 (if product
793 (if (plist-member s :product)
794 (equal (plist-get s :product) product)
795 t)
796 t)
797 ;; Is USER specified, in the entry, and they are equal
798 (if user
799 (if (plist-member s :user)
800 (equal (plist-get s :user) user)
801 t)
802 t)
803 ;; Is PORT specified, in the entry, and they are equal
804 (if port
805 (if (plist-member s :port)
806 (equal (plist-get s :port) port)
807 t)
808 t))
809 ;; Is HOST specified, in the entry, and they are equal
810 ;; then the H-SECRET list
811 (if (and host
812 (plist-member s :host)
813 (equal (plist-get s :host) host))
814 (push s h-secret)
815 ;; Are SERVER and DATABASE specified, present, and equal
816 ;; then the SD-SECRET list
817 (if (and server
818 (plist-member s :server)
819 database
820 (plist-member s :database)
821 (equal (plist-get s :server) server)
822 (equal (plist-get s :database) database))
823 (push s sd-secret)
824 ;; Is SERVER specified, in the entry, and they are equal
825 ;; then the base SECRET list
826 (if (and server
827 (plist-member s :server)
828 (equal (plist-get s :server) server))
829 (push s secret)
830 ;; Is DATABASE specified, in the entry, and they are equal
831 ;; then the base SECRET list
832 (if (and database
833 (plist-member s :database)
834 (equal (plist-get s :database) database))
835 (push s secret)))))))
836 (setq secret (or h-secret sd-secret secret))
837
838 ;; If we found a single secret, return the password
839 (when (= 1 (length secret))
840 (setq secret (car secret))
841 (if (plist-member secret :secret)
842 (plist-get secret :secret)
843 nil))))
844
845(defcustom sql-password-wallet
846 (let (wallet w)
847 (dolist (ext '(".json.gpg" ".gpg" ".json" "") wallet)
848 (unless wallet
849 (setq w (locate-user-emacs-file (concat "sql-wallet" ext)
850 (concat ".sql-wallet" ext)))
851 (when (file-exists-p w)
852 (setq wallet w)))))
853 "Identification of the password wallet.
854See `sql-password-search-wallet-function' to understand how this value
855is used to locate the password wallet."
856 :type `(plist-get (symbol-plist 'auth-sources) 'custom-type)
857 :group 'SQL
858 :version "27.1")
859
860(defvar sql-password-search-wallet-function #'sql-auth-source-search-wallet
861 "Function to handle the lookup of the database password.
862The specified function will be called as:
863 (wallet-func WALLET PRODUCT USER SERVER DATABASE PORT)
864
865It is expected to return either a string containing the password,
866a function returning the password, or nil, If you want to support
867another format of password file, then implement a different
868search wallet function and identify the location of the password
869store with `sql-password-wallet'.")
870
751;; misc customization of sql.el behavior 871;; misc customization of sql.el behavior
752 872
753(defcustom sql-electric-stuff nil 873(defcustom sql-electric-stuff nil
@@ -3199,6 +3319,10 @@ symbol `password', for the server if it contains the symbol
3199`database'. The members of WHAT are processed in the order in 3319`database'. The members of WHAT are processed in the order in
3200which they are provided. 3320which they are provided.
3201 3321
3322If the `sql-password-wallet' is non-nil and WHAT contains the
3323`password' token, then the `password' token will be pushed to the
3324end to be sure that all of the values can be fed to the wallet.
3325
3202Each token may also be a list with the token in the car and a 3326Each token may also be a list with the token in the car and a
3203plist of options as the cdr. The following properties are 3327plist of options as the cdr. The following properties are
3204supported: 3328supported:
@@ -3210,6 +3334,15 @@ supported:
3210 3334
3211In order to ask the user for username, password and database, call the 3335In order to ask the user for username, password and database, call the
3212function like this: (sql-get-login \\='user \\='password \\='database)." 3336function like this: (sql-get-login \\='user \\='password \\='database)."
3337
3338 ;; Push the password to the end if we have a wallet
3339 (when (and sql-password-wallet
3340 (fboundp sql-password-search-wallet-function)
3341 (member 'password what))
3342 (setq what (append (cl-delete 'password what)
3343 '(password))))
3344
3345 ;; Prompt for each parameter
3213 (dolist (w what) 3346 (dolist (w what)
3214 (let ((plist (cdr-safe w))) 3347 (let ((plist (cdr-safe w)))
3215 (pcase (or (car-safe w) w) 3348 (pcase (or (car-safe w) w)
@@ -3218,7 +3351,19 @@ function like this: (sql-get-login \\='user \\='password \\='database)."
3218 3351
3219 ('password 3352 ('password
3220 (setq-default sql-password 3353 (setq-default sql-password
3221 (read-passwd "Password: " nil (sql-default-value 'sql-password)))) 3354 (if (and sql-password-wallet
3355 (fboundp sql-password-search-wallet-function))
3356 (let ((password (funcall sql-password-search-wallet-function
3357 sql-password-wallet
3358 sql-product
3359 sql-user
3360 sql-server
3361 sql-database
3362 sql-port)))
3363 (if password
3364 password
3365 (read-passwd "Password: " nil (sql-default-value 'sql-password))))
3366 (read-passwd "Password: " nil (sql-default-value 'sql-password)))))
3222 3367
3223 ('server 3368 ('server
3224 (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist)) 3369 (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
@@ -4481,6 +4626,10 @@ the call to \\[sql-product-interactive] with
4481 (or sql-default-directory 4626 (or sql-default-directory
4482 default-directory))) 4627 default-directory)))
4483 4628
4629 ;; The password wallet returns a function which supplies the password.
4630 (when (functionp sql-password)
4631 (setq sql-password (funcall sql-password)))
4632
4484 ;; Call the COMINT service 4633 ;; Call the COMINT service
4485 (funcall (sql-get-product-feature product :sqli-comint-func) 4634 (funcall (sql-get-product-feature product :sqli-comint-func)
4486 product 4635 product