Difference between revision 4 and current revision

Summary: Rollback to 2007-06-01 11:09 UTC

No diff available.


;;; otp.el --- a one-time password creator for Emacs -*- emacs-lisp -*-

;; Copyright (C) 2006, 2007 Paul Huff <paul.huff@gmail.com>

;; Author: Paul Huff <paul.huff@gmail.com>
;; Keywords: convenience

;; otp.el is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; {at your option} any later version.

;; otp.el is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING, or type `C-h C-c'. If
;; not, write to the Free Software Foundation at this address:

;;   Free Software Foundation
;;   51 Franklin Street, Fifth Floor
;;   Boston, MA 02110-1301
;;   USA

;; A lot of this stuff was developed with tons of help from #emacs.  Thanks,
;; guys!

;; The canonical place to find out about this file is:
;; http://sf.net/projects/otp-el

;; I added the following functions to my .emacs in order to get tramp
;; to use this code to automatically handle my otp host in a multi-chain... It's
;; worked really well for me.  Enjoy!

;; (setq tramp-otp-prompt-regexp "\\(^.*[rR]esponse\\).*:\^@? *")
;; (defun tramp-action-otp-password (p multi-method method user host)
;;   "Query the user for a password."
;;   (let* ((otp-string (match-string 1))
;; 	(pw-prompt
;; 	 (format "Password for %s (otp: %s) "
;; 		 (tramp-make-tramp-file-name
;; 		  nil method user host "") otp-string)))
;;     (tramp-message 9 "Sending password")
;;     (tramp-enter-otp-password p pw-prompt user host otp-string)))
;; (defun tramp-multi-action-otp-password (p method user host)
;;   "Query the user for a password."
;;   (let* ((otp-string (match-string 1))
;; 	(pw-prompt
;; 	 (format "Password for %s (opt: %s) "
;; 		 (tramp-make-tramp-file-name
;; 		  nil method user host "") otp-string)))
;;     (tramp-message 9 "Sending password")
;;     (tramp-enter-otp-password p pw-prompt user host otp-string)))
;; (defun tramp-enter-otp-password (p prompt user host otp-string)
;;   "Prompt for a password and send it to the remote end.
;; Uses PROMPT as a prompt and sends the password to process P."
;;   (let ((pw (otp-password-filter otp-string (tramp-read-passwd user host prompt))))
;;     (erase-buffer)
;;     (process-send-string
;;      p (concat pw
;; 	       (or (tramp-get-method-parameter
;; 		    tramp-current-multi-method
;; 		    tramp-current-method
;; 		    tramp-current-user
;; 		    tramp-current-host
;; 		    'tramp-password-end-of-line)
;; 		   tramp-default-password-end-of-line)))))
;; (setq tramp-actions-before-shell (cons '(tramp-otp-prompt-regexp tramp-action-otp-password) tramp-actions-before-shell))
;; (setq tramp-multi-actions (cons '(tramp-otp-prompt-regexp tramp-multi-action-otp-password) tramp-multi-actions))

(setq otp-dict '("A"     "ABE"   "ACE"   "ACT"   "AD"    "ADA"   "ADD"
"AGO"   "AID"   "AIM"   "AIR"   "ALL"   "ALP"   "AM"    "AMY"
"AN"    "ANA"   "AND"   "ANN"   "ANT"   "ANY"   "APE"   "APS"
"APT"   "ARC"   "ARE"   "ARK"   "ARM"   "ART"   "AS"    "ASH"
"ASK"   "AT"    "ATE"   "AUG"   "AUK"   "AVE"   "AWE"   "AWK"
"AWL"   "AWN"   "AX"    "AYE"   "BAD"   "BAG"   "BAH"   "BAM"
"BAN"   "BAR"   "BAT"   "BAY"   "BE"    "BED"   "BEE"   "BEG"
"BEN"   "BET"   "BEY"   "BIB"   "BID"   "BIG"   "BIN"   "BIT"
"BOB"   "BOG"   "BON"   "BOO"   "BOP"   "BOW"   "BOY"   "BUB"
"BUD"   "BUG"   "BUM"   "BUN"   "BUS"   "BUT"   "BUY"   "BY"
"BYE"   "CAB"   "CAL"   "CAM"   "CAN"   "CAP"   "CAR"   "CAT"
"CAW"   "COD"   "COG"   "COL"   "CON"   "COO"   "COP"   "COT"
"COW"   "COY"   "CRY"   "CUB"   "CUE"   "CUP"   "CUR"   "CUT"
"DAB"   "DAD"   "DAM"   "DAN"   "DAR"   "DAY"   "DEE"   "DEL"
"DEN"   "DES"   "DEW"   "DID"   "DIE"   "DIG"   "DIN"   "DIP"
"DO"    "DOE"   "DOG"   "DON"   "DOT"   "DOW"   "DRY"   "DUB"
"DUD"   "DUE"   "DUG"   "DUN"   "EAR"   "EAT"   "ED"    "EEL"
"EGG"   "EGO"   "ELI"   "ELK"   "ELM"   "ELY"   "EM"    "END"
"EST"   "ETC"   "EVA"   "EVE"   "EWE"   "EYE"   "FAD"   "FAN"
"FAR"   "FAT"   "FAY"   "FED"   "FEE"   "FEW"   "FIB"   "FIG"
"FIN"   "FIR"   "FIT"   "FLO"   "FLY"   "FOE"   "FOG"   "FOR"
"FRY"   "FUM"   "FUN"   "FUR"   "GAB"   "GAD"   "GAG"   "GAL"
"GAM"   "GAP"   "GAS"   "GAY"   "GEE"   "GEL"   "GEM"   "GET"
"GIG"   "GIL"   "GIN"   "GO"    "GOT"   "GUM"   "GUN"   "GUS"
"GUT"   "GUY"   "GYM"   "GYP"   "HA"    "HAD"   "HAL"   "HAM"
"HAN"   "HAP"   "HAS"   "HAT"   "HAW"   "HAY"   "HE"    "HEM"
"HEN"   "HER"   "HEW"   "HEY"   "HI"    "HID"   "HIM"   "HIP"
"HIS"   "HIT"   "HO"    "HOB"   "HOC"   "HOE"   "HOG"   "HOP"
"HOT"   "HOW"   "HUB"   "HUE"   "HUG"   "HUH"   "HUM"   "HUT"
"I"     "ICY"   "IDA"   "IF"    "IKE"   "ILL"   "INK"   "INN"
"IO"    "ION"   "IQ"    "IRA"   "IRE"   "IRK"   "IS"    "IT"
"ITS"   "IVY"   "JAB"   "JAG"   "JAM"   "JAN"   "JAR"   "JAW"
"JAY"   "JET"   "JIG"   "JIM"   "JO"    "JOB"   "JOE"   "JOG"
"JOT"   "JOY"   "JUG"   "JUT"   "KAY"   "KEG"   "KEN"   "KEY"
"KID"   "KIM"   "KIN"   "KIT"   "LA"    "LAB"   "LAC"   "LAD"
"LAG"   "LAM"   "LAP"   "LAW"   "LAY"   "LEA"   "LED"   "LEE"
"LEG"   "LEN"   "LEO"   "LET"   "LEW"   "LID"   "LIE"   "LIN"
"LIP"   "LIT"   "LO"    "LOB"   "LOG"   "LOP"   "LOS"   "LOT"
"LOU"   "LOW"   "LOY"   "LUG"   "LYE"   "MA"    "MAC"   "MAD"
"MAE"   "MAN"   "MAO"   "MAP"   "MAT"   "MAW"   "MAY"   "ME"
"MEG"   "MEL"   "MEN"   "MET"   "MEW"   "MID"   "MIN"   "MIT"
"MOB"   "MOD"   "MOE"   "MOO"   "MOP"   "MOS"   "MOT"   "MOW"
"MUD"   "MUG"   "MUM"   "MY"    "NAB"   "NAG"   "NAN"   "NAP"
"NAT"   "NAY"   "NE"    "NED"   "NEE"   "NET"   "NEW"   "NIB"
"NIL"   "NIP"   "NIT"   "NO"    "NOB"   "NOD"   "NON"   "NOR"
"NOT"   "NOV"   "NOW"   "NU"    "NUN"   "NUT"   "O"     "OAF"
"OAK"   "OAR"   "OAT"   "ODD"   "ODE"   "OF"    "OFF"   "OFT"
"OH"    "OIL"   "OK"    "OLD"   "ON"    "ONE"   "OR"    "ORB"
"ORE"   "ORR"   "OS"    "OTT"   "OUR"   "OUT"   "OVA"   "OW"
"OWE"   "OWL"   "OWN"   "OX"    "PA"    "PAD"   "PAL"   "PAM"
"PAN"   "PAP"   "PAR"   "PAT"   "PAW"   "PAY"   "PEA"   "PEG"
"PEN"   "PEP"   "PER"   "PET"   "PEW"   "PHI"   "PI"    "PIE"
"PIN"   "PIT"   "PLY"   "PO"    "POD"   "POE"   "POP"   "POT"
"POW"   "PRO"   "PRY"   "PUB"   "PUG"   "PUN"   "PUP"   "PUT"
"QUO"   "RAG"   "RAM"   "RAN"   "RAP"   "RAT"   "RAW"   "RAY"
"REB"   "RED"   "REP"   "RET"   "RIB"   "RID"   "RIG"   "RIM"
"RIO"   "RIP"   "ROB"   "ROD"   "ROE"   "RON"   "ROT"   "ROW"
"ROY"   "RUB"   "RUE"   "RUG"   "RUM"   "RUN"   "RYE"   "SAC"
"SAD"   "SAG"   "SAL"   "SAM"   "SAN"   "SAP"   "SAT"   "SAW"
"SAY"   "SEA"   "SEC"   "SEE"   "SEN"   "SET"   "SEW"   "SHE"
"SHY"   "SIN"   "SIP"   "SIR"   "SIS"   "SIT"   "SKI"   "SKY"
"SLY"   "SO"    "SOB"   "SOD"   "SON"   "SOP"   "SOW"   "SOY"
"SPA"   "SPY"   "SUB"   "SUD"   "SUE"   "SUM"   "SUN"   "SUP"
"TAB"   "TAD"   "TAG"   "TAN"   "TAP"   "TAR"   "TEA"   "TED"
"TEE"   "TEN"   "THE"   "THY"   "TIC"   "TIE"   "TIM"   "TIN"
"TIP"   "TO"    "TOE"   "TOG"   "TOM"   "TON"   "TOO"   "TOP"
"TOW"   "TOY"   "TRY"   "TUB"   "TUG"   "TUM"   "TUN"   "TWO"
"UN"    "UP"    "US"    "USE"   "VAN"   "VAT"   "VET"   "VIE"
"WAD"   "WAG"   "WAR"   "WAS"   "WAY"   "WE"    "WEB"   "WED"
"WEE"   "WET"   "WHO"   "WHY"   "WIN"   "WIT"   "WOK"   "WON"
"WOO"   "WOW"   "WRY"   "WU"    "YAM"   "YAP"   "YAW"   "YE"
"YEA"   "YES"   "YET"   "YOU"   "ABED"  "ABEL"  "ABET"  "ABLE"

(defun otp-hex-string-to-binary-string (s)
  ;;From sachac on #emacs! Thanks for the help!!
  (mapconcat (lambda (x) (nth (string-to-number x 16)
			      '("0000" "0001" "0010" "0011" "0100" "0101" 
				"0110" "0111" "1000" "1001" "1010" "1011" 
				"1100" "1101" "1110" "1111"))) 
	     (split-string s "" t) ""))

(defun otp-fold (s)
  (let ((result "")
	(n 0))
    (while (< n 16)
      (setq result (concat result (format "%x" 
					    (substring s n (1+ n)) 16)
					    (substring s (+ n 16) (+ n 17)) 16)))))
      (setq n (1+ n)))

(defun otp-hex-string-to-string (s)
  (let ((n 0)
	(result ""))
    (while (< n (length s))
      (setq result (concat result 
			   (list (string-to-number (substring s n (+ n 2)) 16))))
      (setq n (+ n 2)))

(defun otp-add-checksum (s)
  (let ((sum 0)
	(n 0)
	(result ""))
	(while (< n (length s))
	  (setq sum (+ sum (string-to-number (substring s n (+ n 2)) 2)))
	  (setq n (+ n 2)))
	(setq result (otp-hex-string-to-binary-string (format "%x" sum)))
	(concat s (substring result (- (length result) 2) (length result)))))
(defun otp-hex-string-to-words (s)
  (let* ((binary-string (otp-hex-string-to-binary-string s))
	(binary-string-plus (otp-add-checksum binary-string))
	(dict-indices (otp-string-partition binary-string-plus 11)))
;;    (setq blah-indices dict-indices)
;;    (setq blah-array (mapcar (lambda (x) (string-to-number x 2)) dict-indices))
    (mapconcat (lambda (x) (nth (string-to-number x 2) otp-dict)) dict-indices " ")
(defun otp-string-partition (s slength)
  (if (= (length s) 0) '()
    (cons (substring s 0 (+ 0 slength))
	  (otp-string-partition (substring s slength (length s)) slength))))

(defun otp-gen (times seed secret)
  (let ((s (otp-fold (md5 (concat (downcase seed) secret))))
	(n 0))
    (while (< n times)
      (setq s (otp-fold (md5 (otp-hex-string-to-string s))))
      (setq n (+ n 1)))
  ;;  (setq blah s)
    (otp-hex-string-to-words s)))

(defun otp-password-filter (prompt-string password)
  (if (not (equal (string-match "^otp-md5 \\([0-9]+\\) \\(.*\\) ext, Response" prompt-string) 'nil))
      (let ((pw (otp-gen (string-to-number (match-string 1 prompt-string)) (match-string 2 prompt-string) password)))

(provide 'otp)