kmpoppe

putty.vbs with 1password support

Feb 2nd, 2019
2,528
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VBScript 13.85 KB | None | 0 0
  1. ' This script is primarily maintained on Github: https://gist.github.com/kmpoppe/52ff04186f52e20078f66da7e4d9ff6b
  2. '
  3. ' The aim of this script is to execute putty with parameters like ssh://login@host directly using an URL in a browser
  4. '
  5. ' Update 2019-02-02, Kai Michael Poppe (twitter @kmpoppe):
  6. ' This script now also accepts item and vault data from 1password so that you can log in to putty without having
  7. ' username and password in the URL but getting it from your 1password vault. The script now makes use of a Json lib
  8. ' by "demon" (http://demon.tw/my-work/vbs-json.html)
  9. '
  10. ' Installation:
  11. '   - Launch putty.reg to associate ssh:// and telnet:// to this script
  12. '   - Edit the putty path in parameter below like puttyPath = "C:\Program Files (x86)\putty.exe"
  13. '   - Save this .vbs on your PC like c:\putty.vbs (or change the path in putty.reg)
  14. ' If you want to use the script with 1password:
  15. '   - Get 1password CLI-tool from https://app-updates.agilebits.com/product_history/CLI
  16. '   - Read how to get a signin session (variable opSession below): https://support.1password.com/command-line/
  17. ' Uninstallation:
  18. '   - Run unputty.reg
  19. ' Version 2014-04-23'
  20. ' Script Created by Sebastien Biffi
  21. '
  22. ' Source Original: https://gist.github.com/sbiffi
  23.  
  24. puttyPath = "C:\Program Files\putty\putty.exe"
  25. opPath = "<PATH TO OP.EXE>\op.exe"
  26. opSession = "<SESSION ID FROM OP SIGNIN>"
  27.  
  28. On Error Resume Next
  29. ' initialisation of variables
  30. logResult = "" ' Used for logging purpose during debug or in case of error. Log is a msgBox
  31. logIcon = 0 ' Icon of the MsgBox. By default: none
  32. logTitle = "" ' Title of the MsgBox. By default: none
  33. Set objShell = CreateObject("WScript.Shell")
  34.  
  35. Set re = New RegExp
  36. ' The pattern that matches the URL. Used to check the URL format provided and find fields in it.
  37. re.Pattern = "^([^:]+)://(([^:]+)(:(.*))?@)?(([^/@:]+)(:([0-9]+))?)/?(\?onepasswdfill=(.*)\&onepasswdvault=(.*))?$"
  38.  
  39. ' Check if only 1 parameter is passed to the script, else throw an error
  40. if Wscript.Arguments.Count = 1 then
  41.     url = Wscript.Arguments(0
  42. else
  43.     exitWithError("Please pass only 1 parameter to this script like:" & vbCrLf & "   - ssh://login:password@host:port " & vbCrLf & "   - telnet://login@host:port" & vbCrLf & "login, password & port are optional")
  44. end if
  45.  
  46. ' Check if the URL is valid, else throw an error
  47. If re.Test(url) Then
  48.     log("URL is valid: " & url)
  49. Else
  50.     exitWithError(url & " is NOT a valid URL" & vbCrLf & "Please pass only 1 parameter to this script like:" & vbCrLf & "   - ssh://login:password@host:port " & vbCrLf & "   - telnet://login@host:port" & vbCrLf & "login, password & port are optional")
  51. End If
  52.  
  53. ' Find the putty parameters in the URL
  54. Set Matches = re.Execute(url)
  55. protocol = Matches.Item(0).Submatches(0)
  56. login = Matches.Item(0).Submatches(2)
  57. pwd = Matches.Item(0).Submatches(4)
  58. host = Matches.Item(0).Submatches(6)
  59. port = Matches.Item(0).Submatches(8)
  60.  
  61. ' See if 1Password url parts are provided and replace user/password from the item
  62. opwditem = Matches.Item(0).Submatches(10)
  63. opwdvault = Matches.Item(0).Submatches(11)
  64.  
  65. If opwditem <> "" And opwdvault <> "" Then
  66.     Dim opExecStatement, strTempFileName, opJson
  67.     Set fso = CreateObject("Scripting.FileSystemObject")
  68.  
  69.     strTempFileName = fso.GetSpecialFolder(2) & "\" & fso.GetTempName
  70.     opExecStatement = opPath & " get item " & opwditem & " --vault=" & opwdvault & " --session=" & opSession & " > " & strTempFileName
  71.     Set returnValue = objShell.Run("cmd /c " & opExecStatement, 0, true)
  72.    
  73.     Set jsonFile = fso.OpenTextFile(strTempFileName, 1)
  74.     opJson = jsonFile.ReadAll
  75.     jsonFile.Close
  76.     fso.DeleteFile strTempFileName
  77.    
  78.     Dim json, o, i
  79.     Set json = New VbsJson
  80.     Set o = json.Decode(opJson)
  81.     For Each i In o("details")("fields")
  82.         If i("designation") = "username" Then login = i("value")
  83.         If i("designation") = "password" Then pwd = i("value")
  84.     Next
  85. End If
  86.  
  87. log("  host: " & host)
  88. log("  protocol: " & protocol)
  89. log("  port: " & port)
  90. log("  login: " & login)
  91. log("  pwd: " & pwd)
  92.  
  93. if protocol = "ssh" then
  94.     paramProtocol = " -ssh"
  95. elseif protocol = "telnet" then
  96.     paramProtocol = " -telnet"
  97. else
  98.     exitWithError("Protocol: " & protocol & " is not a valid protocol (ssh or telnet).")
  99. end if
  100. if host <> "" then
  101.     paramHost = " " & host
  102. else
  103.     exitWithError("Host cannot bu null.")
  104. end if
  105. if login <> "" then
  106.     paramLogin = " -l " & login
  107. end if
  108. if (pwd <> "") and (protocol <> "telnet") then
  109.     paramPwd = " -pw " & pwd
  110. end if
  111. if port <> "" then
  112.     paramPort = " -P " & port
  113. end if
  114.  
  115. ' build the putty command like:
  116. ' putty.exe -ssh host -l login -pw password -P port
  117. ' putty.exe -telnet host -l login -P port
  118. puttyCommand = chr(34) & puttyPath & chr(34) & paramProtocol & paramHost & paramLogin & paramPwd & paramPort
  119. log (puttyCommand)
  120.  
  121. ' For debugging purpose, uncomment following line:
  122. 'outputLog()
  123.  
  124. ' Execute putty
  125. objShell.Run puttyCommand,1,False
  126.  
  127. ' ****************
  128. '   Error Output
  129. ' ****************
  130. ' Outputs a msgBox including the log and the error message
  131. function exitWithError(str)
  132.     log(str)
  133.   logIcon = vbCritical
  134.     logTitle = "Error"
  135.     outputLog()
  136.     wscript.Quit
  137. end function
  138.  
  139. ' ***********
  140. '   Logging
  141. ' ***********
  142. ' Adds a message to the log String
  143. function log(str)
  144.     if logResult = "" then
  145.         logResult = str
  146.     else
  147.         logResult = logResult & vbCrLf & str
  148.     end if
  149. end function
  150. ' Outputs a msgBox including the log String
  151. function outputLog()
  152.     if logResult <> "" then
  153.         MsgBox logResult, logIcon, logTitle
  154.     end if
  155. end function
  156.  
  157. ''' This class is imported here unchanged from the website mentioned below
  158.  
  159. Class VbsJson
  160.     'Author: Demon
  161.     'Date: 2012/5/3
  162.     'Website: http://demon.tw
  163.     Private Whitespace, NumberRegex, StringChunk
  164.     Private b, f, r, n, t
  165.  
  166.     Private Sub Class_Initialize
  167.         Whitespace = " " & vbTab & vbCr & vbLf
  168.         b = ChrW(8)
  169.         f = vbFormFeed
  170.         r = vbCr
  171.         n = vbLf
  172.         t = vbTab
  173.  
  174.         Set NumberRegex = New RegExp
  175.         NumberRegex.Pattern = "(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?"
  176.         NumberRegex.Global = False
  177.         NumberRegex.MultiLine = True
  178.         NumberRegex.IgnoreCase = True
  179.  
  180.         Set StringChunk = New RegExp
  181.         StringChunk.Pattern = "([\s\S]*?)([""\\\x00-\x1f])"
  182.         StringChunk.Global = False
  183.         StringChunk.MultiLine = True
  184.         StringChunk.IgnoreCase = True
  185.     End Sub
  186.    
  187.     'Return a JSON string representation of a VBScript data structure
  188.     'Supports the following objects and types
  189.     '+-------------------+---------------+
  190.     '| VBScript          | JSON          |
  191.     '+===================+===============+
  192.     '| Dictionary        | object        |
  193.     '+-------------------+---------------+
  194.     '| Array             | array         |
  195.     '+-------------------+---------------+
  196.     '| String            | string        |
  197.     '+-------------------+---------------+
  198.     '| Number            | number        |
  199.     '+-------------------+---------------+
  200.     '| True              | true          |
  201.     '+-------------------+---------------+
  202.     '| False             | false         |
  203.     '+-------------------+---------------+
  204.     '| Null              | null          |
  205.     '+-------------------+---------------+
  206.     Public Function Encode(ByRef obj)
  207.         Dim buf, i, c, g
  208.         Set buf = CreateObject("Scripting.Dictionary")
  209.         Select Case VarType(obj)
  210.             Case vbNull
  211.                 buf.Add buf.Count, "null"
  212.             Case vbBoolean
  213.                 If obj Then
  214.                     buf.Add buf.Count, "true"
  215.                 Else
  216.                     buf.Add buf.Count, "false"
  217.                 End If
  218.             Case vbInteger, vbLong, vbSingle, vbDouble
  219.                 buf.Add buf.Count, obj
  220.             Case vbString
  221.                 buf.Add buf.Count, """"
  222.                 For i = 1 To Len(obj)
  223.                     c = Mid(obj, i, 1)
  224.                     Select Case c
  225.                         Case """" buf.Add buf.Count, "\"""
  226.                         Case "\"  buf.Add buf.Count, "\\"
  227.                         Case "/"  buf.Add buf.Count, "/"
  228.                         Case b    buf.Add buf.Count, "\b"
  229.                         Case f    buf.Add buf.Count, "\f"
  230.                         Case r    buf.Add buf.Count, "\r"
  231.                         Case n    buf.Add buf.Count, "\n"
  232.                         Case t    buf.Add buf.Count, "\t"
  233.                         Case Else
  234.                             If AscW(c) >= 0 And AscW(c) <= 31 Then
  235.                                 c = Right("0" & Hex(AscW(c)), 2)
  236.                                 buf.Add buf.Count, "\u00" & c
  237.                             Else
  238.                                 buf.Add buf.Count, c
  239.                             End If
  240.                     End Select
  241.                 Next
  242.                 buf.Add buf.Count, """"
  243.             Case vbArray + vbVariant
  244.                 g = True
  245.                 buf.Add buf.Count, "["
  246.                 For Each i In obj
  247.                     If g Then g = False Else buf.Add buf.Count, ","
  248.                     buf.Add buf.Count, Encode(i)
  249.                 Next
  250.                 buf.Add buf.Count, "]"
  251.             Case vbObject
  252.                 If TypeName(obj) = "Dictionary" Then
  253.                     g = True
  254.                     buf.Add buf.Count, "{"
  255.                     For Each i In obj
  256.                         If g Then g = False Else buf.Add buf.Count, ","
  257.                         buf.Add buf.Count, """" & i & """" & ":" & Encode(obj(i))
  258.                     Next
  259.                     buf.Add buf.Count, "}"
  260.                 Else
  261.                     Err.Raise 8732,,"None dictionary object"
  262.                 End If
  263.             Case Else
  264.                 buf.Add buf.Count, """" & CStr(obj) & """"
  265.         End Select
  266.         Encode = Join(buf.Items, "")
  267.     End Function
  268.  
  269.     'Return the VBScript representation of ``str(``
  270.     'Performs the following translations in decoding
  271.     '+---------------+-------------------+
  272.     '| JSON          | VBScript          |
  273.     '+===============+===================+
  274.     '| object        | Dictionary        |
  275.     '+---------------+-------------------+
  276.     '| array         | Array             |
  277.     '+---------------+-------------------+
  278.     '| string        | String            |
  279.     '+---------------+-------------------+
  280.     '| number        | Double            |
  281.     '+---------------+-------------------+
  282.     '| true          | True              |
  283.     '+---------------+-------------------+
  284.     '| false         | False             |
  285.     '+---------------+-------------------+
  286.     '| null          | Null              |
  287.     '+---------------+-------------------+
  288.     Public Function Decode(ByRef str)
  289.         Dim idx
  290.         idx = SkipWhitespace(str, 1)
  291.  
  292.         If Mid(str, idx, 1) = "{" Then
  293.             Set Decode = ScanOnce(str, 1)
  294.         Else
  295.             Decode = ScanOnce(str, 1)
  296.         End If
  297.     End Function
  298.    
  299.     Private Function ScanOnce(ByRef str, ByRef idx)
  300.         Dim c, ms
  301.  
  302.         idx = SkipWhitespace(str, idx)
  303.         c = Mid(str, idx, 1)
  304.  
  305.         If c = "{" Then
  306.             idx = idx + 1
  307.             Set ScanOnce = ParseObject(str, idx)
  308.             Exit Function
  309.         ElseIf c = "[" Then
  310.             idx = idx + 1
  311.             ScanOnce = ParseArray(str, idx)
  312.             Exit Function
  313.         ElseIf c = """" Then
  314.             idx = idx + 1
  315.             ScanOnce = ParseString(str, idx)
  316.             Exit Function
  317.         ElseIf c = "n" And StrComp("null", Mid(str, idx, 4)) = 0 Then
  318.             idx = idx + 4
  319.             ScanOnce = Null
  320.             Exit Function
  321.         ElseIf c = "t" And StrComp("true", Mid(str, idx, 4)) = 0 Then
  322.             idx = idx + 4
  323.             ScanOnce = True
  324.             Exit Function
  325.         ElseIf c = "f" And StrComp("false", Mid(str, idx, 5)) = 0 Then
  326.             idx = idx + 5
  327.             ScanOnce = False
  328.             Exit Function
  329.         End If
  330.        
  331.         Set ms = NumberRegex.Execute(Mid(str, idx))
  332.         If ms.Count = 1 Then
  333.             idx = idx + ms(0).Length
  334.             ScanOnce = CDbl(ms(0))
  335.             Exit Function
  336.         End If
  337.        
  338.         Err.Raise 8732,,"No JSON object could be ScanOnced"
  339.     End Function
  340.  
  341.     Private Function ParseObject(ByRef str, ByRef idx)
  342.         Dim c, key, value
  343.         Set ParseObject = CreateObject("Scripting.Dictionary")
  344.         idx = SkipWhitespace(str, idx)
  345.         c = Mid(str, idx, 1)
  346.        
  347.         If c = "}" Then
  348.             Exit Function
  349.         ElseIf c <> """" Then
  350.             Err.Raise 8732,,"Expecting property name"
  351.         End If
  352.  
  353.         idx = idx + 1
  354.        
  355.         Do
  356.             key = ParseString(str, idx)
  357.  
  358.             idx = SkipWhitespace(str, idx)
  359.             If Mid(str, idx, 1) <> ":" Then
  360.                 Err.Raise 8732,,"Expecting : delimiter"
  361.             End If
  362.  
  363.             idx = SkipWhitespace(str, idx + 1)
  364.             If Mid(str, idx, 1) = "{" Then
  365.                 Set value = ScanOnce(str, idx)
  366.             Else
  367.                 value = ScanOnce(str, idx)
  368.             End If
  369.             ParseObject.Add key, value
  370.  
  371.             idx = SkipWhitespace(str, idx)
  372.             c = Mid(str, idx, 1)
  373.             If c = "}" Then
  374.                 Exit Do
  375.             ElseIf c <> "," Then
  376.                 Err.Raise 8732,,"Expecting , delimiter"
  377.             End If
  378.  
  379.             idx = SkipWhitespace(str, idx + 1)
  380.             c = Mid(str, idx, 1)
  381.             If c <> """" Then
  382.                 Err.Raise 8732,,"Expecting property name"
  383.             End If
  384.  
  385.             idx = idx + 1
  386.         Loop
  387.  
  388.         idx = idx + 1
  389.     End Function
  390.    
  391.     Private Function ParseArray(ByRef str, ByRef idx)
  392.         Dim c, values, value
  393.         Set values = CreateObject("Scripting.Dictionary")
  394.         idx = SkipWhitespace(str, idx)
  395.         c = Mid(str, idx, 1)
  396.  
  397.         If c = "]" Then
  398.             ParseArray = values.Items
  399.             Exit Function
  400.         End If
  401.  
  402.         Do
  403.             idx = SkipWhitespace(str, idx)
  404.             If Mid(str, idx, 1) = "{" Then
  405.                 Set value = ScanOnce(str, idx)
  406.             Else
  407.                 value = ScanOnce(str, idx)
  408.             End If
  409.             values.Add values.Count, value
  410.  
  411.             idx = SkipWhitespace(str, idx)
  412.             c = Mid(str, idx, 1)
  413.             If c = "]" Then
  414.                 Exit Do
  415.             ElseIf c <> "," Then
  416.                 Err.Raise 8732,,"Expecting , delimiter"
  417.             End If
  418.  
  419.             idx = idx + 1
  420.         Loop
  421.  
  422.         idx = idx + 1
  423.         ParseArray = values.Items
  424.     End Function
  425.    
  426.     Private Function ParseString(ByRef str, ByRef idx)
  427.         Dim chunks, content, terminator, ms, esc, char
  428.         Set chunks = CreateObject("Scripting.Dictionary")
  429.  
  430.         Do
  431.             Set ms = StringChunk.Execute(Mid(str, idx))
  432.             If ms.Count = 0 Then
  433.                 Err.Raise 8732,,"Unterminated string starting"
  434.             End If
  435.            
  436.             content = ms(0).Submatches(0)
  437.             terminator = ms(0).Submatches(1)
  438.             If Len(content) > 0 Then
  439.                 chunks.Add chunks.Count, content
  440.             End If
  441.            
  442.             idx = idx + ms(0).Length
  443.            
  444.             If terminator = """" Then
  445.                 Exit Do
  446.             ElseIf terminator <> "\" Then
  447.                 Err.Raise 8732,,"Invalid control character"
  448.             End If
  449.            
  450.             esc = Mid(str, idx, 1)
  451.  
  452.             If esc <> "u" Then
  453.                 Select Case esc
  454.                     Case """" char = """"
  455.                     Case "\"  char = "\"
  456.                     Case "/"  char = "/"
  457.                     Case "b"  char = b
  458.                     Case "f"  char = f
  459.                     Case "n"  char = n
  460.                     Case "r"  char = r
  461.                     Case "t"  char = t
  462.                     Case Else Err.Raise 8732,,"Invalid escape"
  463.                 End Select
  464.                 idx = idx + 1
  465.             Else
  466.                 char = ChrW("&H" & Mid(str, idx + 1, 4))
  467.                 idx = idx + 5
  468.             End If
  469.  
  470.             chunks.Add chunks.Count, char
  471.         Loop
  472.  
  473.         ParseString = Join(chunks.Items, "")
  474.     End Function
  475.  
  476.     Private Function SkipWhitespace(ByRef str, ByVal idx)
  477.         Do While idx <= Len(str) And _
  478.             InStr(Whitespace, Mid(str, idx, 1)) > 0
  479.             idx = idx + 1
  480.         Loop
  481.         SkipWhitespace = idx
  482.     End Function
  483.  
  484. End Class
Advertisement