Page MenuHomeMusing Studio

No OneTemporary

diff --git a/src/github.com/howeyc/gopass/.travis.yml b/src/github.com/howeyc/gopass/.travis.yml
new file mode 100644
index 0000000..cc5d509
--- /dev/null
+++ b/src/github.com/howeyc/gopass/.travis.yml
@@ -0,0 +1,11 @@
+language: go
+
+os:
+ - linux
+ - osx
+
+go:
+ - 1.3
+ - 1.4
+ - 1.5
+ - tip
diff --git a/src/github.com/howeyc/gopass/LICENSE.txt b/src/github.com/howeyc/gopass/LICENSE.txt
new file mode 100644
index 0000000..14f7470
--- /dev/null
+++ b/src/github.com/howeyc/gopass/LICENSE.txt
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2012 Chris Howey
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/github.com/howeyc/gopass/OPENSOLARIS.LICENSE b/src/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
new file mode 100644
index 0000000..da23621
--- /dev/null
+++ b/src/github.com/howeyc/gopass/OPENSOLARIS.LICENSE
@@ -0,0 +1,384 @@
+Unless otherwise noted, all files in this distribution are released
+under the Common Development and Distribution License (CDDL).
+Exceptions are noted within the associated source files.
+
+--------------------------------------------------------------------
+
+
+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
+
+1. Definitions.
+
+ 1.1. "Contributor" means each individual or entity that creates
+ or contributes to the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Software, prior Modifications used by a Contributor (if any),
+ and the Modifications made by that particular Contributor.
+
+ 1.3. "Covered Software" means (a) the Original Software, or (b)
+ Modifications, or (c) the combination of files containing
+ Original Software with files containing Modifications, in
+ each case including portions thereof.
+
+ 1.4. "Executable" means the Covered Software in any form other
+ than Source Code.
+
+ 1.5. "Initial Developer" means the individual or entity that first
+ makes Original Software available under this License.
+
+ 1.6. "Larger Work" means a work which combines Covered Software or
+ portions thereof with code not governed by the terms of this
+ License.
+
+ 1.7. "License" means this document.
+
+ 1.8. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed
+ herein.
+
+ 1.9. "Modifications" means the Source Code and Executable form of
+ any of the following:
+
+ A. Any file that results from an addition to, deletion from or
+ modification of the contents of a file containing Original
+ Software or previous Modifications;
+
+ B. Any new file that contains any part of the Original
+ Software or previous Modifications; or
+
+ C. Any new file that is contributed or otherwise made
+ available under the terms of this License.
+
+ 1.10. "Original Software" means the Source Code and Executable
+ form of computer software code that is originally released
+ under this License.
+
+ 1.11. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by
+ grantor.
+
+ 1.12. "Source Code" means (a) the common form of computer software
+ code in which modifications are made and (b) associated
+ documentation included in or with such code.
+
+ 1.13. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms
+ of, this License. For legal entities, "You" includes any
+ entity which controls, is controlled by, or is under common
+ control with You. For purposes of this definition,
+ "control" means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty
+ percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants.
+
+ 2.1. The Initial Developer Grant.
+
+ Conditioned upon Your compliance with Section 3.1 below and
+ subject to third party intellectual property claims, the Initial
+ Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer, to use,
+ reproduce, modify, display, perform, sublicense and
+ distribute the Original Software (or portions thereof),
+ with or without Modifications, and/or as part of a Larger
+ Work; and
+
+ (b) under Patent Claims infringed by the making, using or
+ selling of Original Software, to make, have made, use,
+ practice, sell, and offer for sale, and/or otherwise
+ dispose of the Original Software (or portions thereof).
+
+ (c) The licenses granted in Sections 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ or otherwise makes the Original Software available to a
+ third party under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: (1) for code that You delete from the Original
+ Software, or (2) for infringements caused by: (i) the
+ modification of the Original Software, or (ii) the
+ combination of the Original Software with other software
+ or devices.
+
+ 2.2. Contributor Grant.
+
+ Conditioned upon Your compliance with Section 3.1 below and
+ subject to third party intellectual property claims, each
+ Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor to use, reproduce,
+ modify, display, perform, sublicense and distribute the
+ Modifications created by such Contributor (or portions
+ thereof), either on an unmodified basis, with other
+ Modifications, as Covered Software and/or as part of a
+ Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either
+ alone and/or in combination with its Contributor Version
+ (or portions of such combination), to make, use, sell,
+ offer for sale, have made, and/or otherwise dispose of:
+ (1) Modifications made by that Contributor (or portions
+ thereof); and (2) the combination of Modifications made by
+ that Contributor with its Contributor Version (or portions
+ of such combination).
+
+ (c) The licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first distributes or
+ otherwise makes the Modifications available to a third
+ party.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: (1) for any code that Contributor has deleted
+ from the Contributor Version; (2) for infringements caused
+ by: (i) third party modifications of Contributor Version,
+ or (ii) the combination of Modifications made by that
+ Contributor with other software (except as part of the
+ Contributor Version) or other devices; or (3) under Patent
+ Claims infringed by Covered Software in the absence of
+ Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Availability of Source Code.
+
+ Any Covered Software that You distribute or otherwise make
+ available in Executable form must also be made available in Source
+ Code form and that Source Code form must be distributed only under
+ the terms of this License. You must include a copy of this
+ License with every copy of the Source Code form of the Covered
+ Software You distribute or otherwise make available. You must
+ inform recipients of any such Covered Software in Executable form
+ as to how they can obtain such Covered Software in Source Code
+ form in a reasonable manner on or through a medium customarily
+ used for software exchange.
+
+ 3.2. Modifications.
+
+ The Modifications that You create or to which You contribute are
+ governed by the terms of this License. You represent that You
+ believe Your Modifications are Your original creation(s) and/or
+ You have sufficient rights to grant the rights conveyed by this
+ License.
+
+ 3.3. Required Notices.
+
+ You must include a notice in each of Your Modifications that
+ identifies You as the Contributor of the Modification. You may
+ not remove or alter any copyright, patent or trademark notices
+ contained within the Covered Software, or any notices of licensing
+ or any descriptive text giving attribution to any Contributor or
+ the Initial Developer.
+
+ 3.4. Application of Additional Terms.
+
+ You may not offer or impose any terms on any Covered Software in
+ Source Code form that alters or restricts the applicable version
+ of this License or the recipients' rights hereunder. You may
+ choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of
+ Covered Software. However, you may do so only on Your own behalf,
+ and not on behalf of the Initial Developer or any Contributor.
+ You must make it absolutely clear that any such warranty, support,
+ indemnity or liability obligation is offered by You alone, and You
+ hereby agree to indemnify the Initial Developer and every
+ Contributor for any liability incurred by the Initial Developer or
+ such Contributor as a result of warranty, support, indemnity or
+ liability terms You offer.
+
+ 3.5. Distribution of Executable Versions.
+
+ You may distribute the Executable form of the Covered Software
+ under the terms of this License or under the terms of a license of
+ Your choice, which may contain terms different from this License,
+ provided that You are in compliance with the terms of this License
+ and that the license for the Executable form does not attempt to
+ limit or alter the recipient's rights in the Source Code form from
+ the rights set forth in this License. If You distribute the
+ Covered Software in Executable form under a different license, You
+ must make it absolutely clear that any terms which differ from
+ this License are offered by You alone, not by the Initial
+ Developer or Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred
+ by the Initial Developer or such Contributor as a result of any
+ such terms You offer.
+
+ 3.6. Larger Works.
+
+ You may create a Larger Work by combining Covered Software with
+ other code not governed by the terms of this License and
+ distribute the Larger Work as a single product. In such a case,
+ You must make sure the requirements of this License are fulfilled
+ for the Covered Software.
+
+4. Versions of the License.
+
+ 4.1. New Versions.
+
+ Sun Microsystems, Inc. is the initial license steward and may
+ publish revised and/or new versions of this License from time to
+ time. Each version will be given a distinguishing version number.
+ Except as provided in Section 4.3, no one other than the license
+ steward has the right to modify this License.
+
+ 4.2. Effect of New Versions.
+
+ You may always continue to use, distribute or otherwise make the
+ Covered Software available under the terms of the version of the
+ License under which You originally received the Covered Software.
+ If the Initial Developer includes a notice in the Original
+ Software prohibiting it from being distributed or otherwise made
+ available under any subsequent version of the License, You must
+ distribute and make the Covered Software available under the terms
+ of the version of the License under which You originally received
+ the Covered Software. Otherwise, You may also choose to use,
+ distribute or otherwise make the Covered Software available under
+ the terms of any subsequent version of the License published by
+ the license steward.
+
+ 4.3. Modified Versions.
+
+ When You are an Initial Developer and You want to create a new
+ license for Your Original Software, You may create and use a
+ modified version of this License if You: (a) rename the license
+ and remove any references to the name of the license steward
+ (except to note that the license differs from this License); and
+ (b) otherwise make it clear that the license contains terms which
+ differ from this License.
+
+5. DISCLAIMER OF WARRANTY.
+
+ COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS"
+ BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+ INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED
+ SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
+ PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
+ PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY
+ COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+ INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
+ NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
+ WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
+ DISCLAIMER.
+
+6. TERMINATION.
+
+ 6.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to
+ cure such breach within 30 days of becoming aware of the breach.
+ Provisions which, by their nature, must remain in effect beyond
+ the termination of this License shall survive.
+
+ 6.2. If You assert a patent infringement claim (excluding
+ declaratory judgment actions) against Initial Developer or a
+ Contributor (the Initial Developer or Contributor against whom You
+ assert such claim is referred to as "Participant") alleging that
+ the Participant Software (meaning the Contributor Version where
+ the Participant is a Contributor or the Original Software where
+ the Participant is the Initial Developer) directly or indirectly
+ infringes any patent, then any and all rights granted directly or
+ indirectly to You by such Participant, the Initial Developer (if
+ the Initial Developer is not the Participant) and all Contributors
+ under Sections 2.1 and/or 2.2 of this License shall, upon 60 days
+ notice from Participant terminate prospectively and automatically
+ at the expiration of such 60 day notice period, unless if within
+ such 60 day period You withdraw Your claim with respect to the
+ Participant Software against such Participant either unilaterally
+ or pursuant to a written agreement with Participant.
+
+ 6.3. In the event of termination under Sections 6.1 or 6.2 above,
+ all end user licenses that have been validly granted by You or any
+ distributor hereunder prior to termination (excluding licenses
+ granted to You by any distributor) shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+ INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
+ COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
+ LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+ CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
+ LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK
+ STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
+ INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
+ APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO
+ NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT
+ APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+ The Covered Software is a "commercial item," as that term is
+ defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
+ computer software" (as that term is defined at 48
+ C.F.R. 252.227-7014(a)(1)) and "commercial computer software
+ documentation" as such terms are used in 48 C.F.R. 12.212
+ (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48
+ C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
+ U.S. Government End Users acquire Covered Software with only those
+ rights set forth herein. This U.S. Government Rights clause is in
+ lieu of, and supersedes, any other FAR, DFAR, or other clause or
+ provision that addresses Government rights in computer software
+ under this License.
+
+9. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed
+ by the law of the jurisdiction specified in a notice contained
+ within the Original Software (except to the extent applicable law,
+ if any, provides otherwise), excluding such jurisdiction's
+ conflict-of-law provisions. Any litigation relating to this
+ License shall be subject to the jurisdiction of the courts located
+ in the jurisdiction and venue specified in a notice contained
+ within the Original Software, with the losing party responsible
+ for costs, including, without limitation, court costs and
+ reasonable attorneys' fees and expenses. The application of the
+ United Nations Convention on Contracts for the International Sale
+ of Goods is expressly excluded. Any law or regulation which
+ provides that the language of a contract shall be construed
+ against the drafter shall not apply to this License. You agree
+ that You alone are responsible for compliance with the United
+ States export administration regulations (and the export control
+ laws and regulation of any other countries) when You use,
+ distribute or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or
+ indirectly, out of its utilization of rights under this License
+ and You agree to work with Initial Developer and Contributors to
+ distribute such responsibility on an equitable basis. Nothing
+ herein is intended or shall be deemed to constitute any admission
+ of liability.
+
+--------------------------------------------------------------------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
+DISTRIBUTION LICENSE (CDDL)
+
+For Covered Software in this distribution, this License shall
+be governed by the laws of the State of California (excluding
+conflict-of-law provisions).
+
+Any litigation relating to this License shall be subject to the
+jurisdiction of the Federal Courts of the Northern District of
+California and the state courts of the State of California, with
+venue lying in Santa Clara County, California.
diff --git a/src/github.com/howeyc/gopass/README.md b/src/github.com/howeyc/gopass/README.md
new file mode 100644
index 0000000..2d6a4e7
--- /dev/null
+++ b/src/github.com/howeyc/gopass/README.md
@@ -0,0 +1,27 @@
+# getpasswd in Go [![GoDoc](https://godoc.org/github.com/howeyc/gopass?status.svg)](https://godoc.org/github.com/howeyc/gopass) [![Build Status](https://secure.travis-ci.org/howeyc/gopass.png?branch=master)](http://travis-ci.org/howeyc/gopass)
+
+Retrieve password from user terminal or piped input without echo.
+
+Verified on BSD, Linux, and Windows.
+
+Example:
+```go
+package main
+
+import "fmt"
+import "github.com/howeyc/gopass"
+
+func main() {
+ fmt.Printf("Password: ")
+
+ // Silent. For printing *'s use gopass.GetPasswdMasked()
+ pass, err := gopass.GetPasswd()
+ if err != nil {
+ // Handle gopass.ErrInterrupted or getch() read error
+ }
+
+ // Do something with pass
+}
+```
+
+Caution: Multi-byte characters not supported!
diff --git a/src/github.com/howeyc/gopass/pass.go b/src/github.com/howeyc/gopass/pass.go
new file mode 100644
index 0000000..f5bd5a5
--- /dev/null
+++ b/src/github.com/howeyc/gopass/pass.go
@@ -0,0 +1,110 @@
+package gopass
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+)
+
+type FdReader interface {
+ io.Reader
+ Fd() uintptr
+}
+
+var defaultGetCh = func(r io.Reader) (byte, error) {
+ buf := make([]byte, 1)
+ if n, err := r.Read(buf); n == 0 || err != nil {
+ if err != nil {
+ return 0, err
+ }
+ return 0, io.EOF
+ }
+ return buf[0], nil
+}
+
+var (
+ maxLength = 512
+ ErrInterrupted = errors.New("interrupted")
+ ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength)
+
+ // Provide variable so that tests can provide a mock implementation.
+ getch = defaultGetCh
+)
+
+// getPasswd returns the input read from terminal.
+// If prompt is not empty, it will be output as a prompt to the user
+// If masked is true, typing will be matched by asterisks on the screen.
+// Otherwise, typing will echo nothing.
+func getPasswd(prompt string, masked bool, r FdReader, w io.Writer) ([]byte, error) {
+ var err error
+ var pass, bs, mask []byte
+ if masked {
+ bs = []byte("\b \b")
+ mask = []byte("*")
+ }
+
+ if isTerminal(r.Fd()) {
+ if oldState, err := makeRaw(r.Fd()); err != nil {
+ return pass, err
+ } else {
+ defer func() {
+ restore(r.Fd(), oldState)
+ fmt.Fprintln(w)
+ }()
+ }
+ }
+
+ if prompt != "" {
+ fmt.Fprint(w, prompt)
+ }
+
+ // Track total bytes read, not just bytes in the password. This ensures any
+ // errors that might flood the console with nil or -1 bytes infinitely are
+ // capped.
+ var counter int
+ for counter = 0; counter <= maxLength; counter++ {
+ if v, e := getch(r); e != nil {
+ err = e
+ break
+ } else if v == 127 || v == 8 {
+ if l := len(pass); l > 0 {
+ pass = pass[:l-1]
+ fmt.Fprint(w, string(bs))
+ }
+ } else if v == 13 || v == 10 {
+ break
+ } else if v == 3 {
+ err = ErrInterrupted
+ break
+ } else if v != 0 {
+ pass = append(pass, v)
+ fmt.Fprint(w, string(mask))
+ }
+ }
+
+ if counter > maxLength {
+ err = ErrMaxLengthExceeded
+ }
+
+ return pass, err
+}
+
+// GetPasswd returns the password read from the terminal without echoing input.
+// The returned byte array does not include end-of-line characters.
+func GetPasswd() ([]byte, error) {
+ return getPasswd("", false, os.Stdin, os.Stdout)
+}
+
+// GetPasswdMasked returns the password read from the terminal, echoing asterisks.
+// The returned byte array does not include end-of-line characters.
+func GetPasswdMasked() ([]byte, error) {
+ return getPasswd("", true, os.Stdin, os.Stdout)
+}
+
+// GetPasswdPrompt prompts the user and returns the password read from the terminal.
+// If mask is true, then asterisks are echoed.
+// The returned byte array does not include end-of-line characters.
+func GetPasswdPrompt(prompt string, mask bool, r FdReader, w io.Writer) ([]byte, error) {
+ return getPasswd(prompt, mask, r, w)
+}
diff --git a/src/github.com/howeyc/gopass/pass_test.go b/src/github.com/howeyc/gopass/pass_test.go
new file mode 100644
index 0000000..7ac3151
--- /dev/null
+++ b/src/github.com/howeyc/gopass/pass_test.go
@@ -0,0 +1,225 @@
+package gopass
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "testing"
+ "time"
+)
+
+// TestGetPasswd tests the password creation and output based on a byte buffer
+// as input to mock the underlying getch() methods.
+func TestGetPasswd(t *testing.T) {
+ type testData struct {
+ input []byte
+
+ // Due to how backspaces are written, it is easier to manually write
+ // each expected output for the masked cases.
+ masked string
+ password string
+ byesLeft int
+ reason string
+ }
+
+ ds := []testData{
+ testData{[]byte("abc\n"), "***", "abc", 0, "Password parsing should stop at \\n"},
+ testData{[]byte("abc\r"), "***", "abc", 0, "Password parsing should stop at \\r"},
+ testData{[]byte("a\nbc\n"), "*", "a", 3, "Password parsing should stop at \\n"},
+ testData{[]byte("*!]|\n"), "****", "*!]|", 0, "Special characters shouldn't affect the password."},
+
+ testData{[]byte("abc\r\n"), "***", "abc", 1,
+ "Password parsing should stop at \\r; Windows LINE_MODE should be unset so \\r is not converted to \\r\\n."},
+
+ testData{[]byte{'a', 'b', 'c', 8, '\n'}, "***\b \b", "ab", 0, "Backspace byte should remove the last read byte."},
+ testData{[]byte{'a', 'b', 127, 'c', '\n'}, "**\b \b*", "ac", 0, "Delete byte should remove the last read byte."},
+ testData{[]byte{'a', 'b', 127, 'c', 8, 127, '\n'}, "**\b \b*\b \b\b \b", "", 0, "Successive deletes continue to delete."},
+ testData{[]byte{8, 8, 8, '\n'}, "", "", 0, "Deletes before characters are noops."},
+ testData{[]byte{8, 8, 8, 'a', 'b', 'c', '\n'}, "***", "abc", 0, "Deletes before characters are noops."},
+
+ testData{[]byte{'a', 'b', 0, 'c', '\n'}, "***", "abc", 0,
+ "Nil byte should be ignored due; may get unintended nil bytes from syscalls on Windows."},
+ }
+
+ // Redirecting output for tests as they print to os.Stdout but we want to
+ // capture and test the output.
+ for _, masked := range []bool{true, false} {
+ for _, d := range ds {
+ pipeBytesToStdin(d.input)
+
+ r, w, err := os.Pipe()
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+
+ result, err := getPasswd("", masked, os.Stdin, w)
+ if err != nil {
+ t.Errorf("Error getting password: %s", err.Error())
+ }
+ leftOnBuffer := flushStdin()
+
+ // Test output (masked and unmasked). Delete/backspace actually
+ // deletes, overwrites and deletes again. As a result, we need to
+ // remove those from the pipe afterwards to mimic the console's
+ // interpretation of those bytes.
+ w.Close()
+ output, err := ioutil.ReadAll(r)
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ var expectedOutput []byte
+ if masked {
+ expectedOutput = []byte(d.masked)
+ } else {
+ expectedOutput = []byte("")
+ }
+ if bytes.Compare(expectedOutput, output) != 0 {
+ t.Errorf("Expected output to equal %v (%q) but got %v (%q) instead when masked=%v. %s", expectedOutput, string(expectedOutput), output, string(output), masked, d.reason)
+ }
+
+ if string(result) != d.password {
+ t.Errorf("Expected %q but got %q instead when masked=%v. %s", d.password, result, masked, d.reason)
+ }
+
+ if leftOnBuffer != d.byesLeft {
+ t.Errorf("Expected %v bytes left on buffer but instead got %v when masked=%v. %s", d.byesLeft, leftOnBuffer, masked, d.reason)
+ }
+ }
+ }
+}
+
+// TestPipe ensures we get our expected pipe behavior.
+func TestPipe(t *testing.T) {
+ type testData struct {
+ input string
+ password string
+ expError error
+ }
+ ds := []testData{
+ testData{"abc", "abc", io.EOF},
+ testData{"abc\n", "abc", nil},
+ testData{"abc\r", "abc", nil},
+ testData{"abc\r\n", "abc", nil},
+ }
+
+ for _, d := range ds {
+ _, err := pipeToStdin(d.input)
+ if err != nil {
+ t.Log("Error writing input to stdin:", err)
+ t.FailNow()
+ }
+ pass, err := GetPasswd()
+ if string(pass) != d.password {
+ t.Errorf("Expected %q but got %q instead.", d.password, string(pass))
+ }
+ if err != d.expError {
+ t.Errorf("Expected %v but got %q instead.", d.expError, err)
+ }
+ }
+}
+
+// flushStdin reads from stdin for .5 seconds to ensure no bytes are left on
+// the buffer. Returns the number of bytes read.
+func flushStdin() int {
+ ch := make(chan byte)
+ go func(ch chan byte) {
+ reader := bufio.NewReader(os.Stdin)
+ for {
+ b, err := reader.ReadByte()
+ if err != nil { // Maybe log non io.EOF errors, if you want
+ close(ch)
+ return
+ }
+ ch <- b
+ }
+ close(ch)
+ }(ch)
+
+ numBytes := 0
+ for {
+ select {
+ case _, ok := <-ch:
+ if !ok {
+ return numBytes
+ }
+ numBytes++
+ case <-time.After(500 * time.Millisecond):
+ return numBytes
+ }
+ }
+ return numBytes
+}
+
+// pipeToStdin pipes the given string onto os.Stdin by replacing it with an
+// os.Pipe. The write end of the pipe is closed so that EOF is read after the
+// final byte.
+func pipeToStdin(s string) (int, error) {
+ pipeReader, pipeWriter, err := os.Pipe()
+ if err != nil {
+ fmt.Println("Error getting os pipes:", err)
+ os.Exit(1)
+ }
+ os.Stdin = pipeReader
+ w, err := pipeWriter.WriteString(s)
+ pipeWriter.Close()
+ return w, err
+}
+
+func pipeBytesToStdin(b []byte) (int, error) {
+ return pipeToStdin(string(b))
+}
+
+// TestGetPasswd_Err tests errors are properly handled from getch()
+func TestGetPasswd_Err(t *testing.T) {
+ var inBuffer *bytes.Buffer
+ getch = func(io.Reader) (byte, error) {
+ b, err := inBuffer.ReadByte()
+ if err != nil {
+ return 13, err
+ }
+ if b == 'z' {
+ return 'z', fmt.Errorf("Forced error; byte returned should not be considered accurate.")
+ }
+ return b, nil
+ }
+ defer func() { getch = defaultGetCh }()
+
+ for input, expectedPassword := range map[string]string{"abc": "abc", "abzc": "ab"} {
+ inBuffer = bytes.NewBufferString(input)
+ p, err := GetPasswdMasked()
+ if string(p) != expectedPassword {
+ t.Errorf("Expected %q but got %q instead.", expectedPassword, p)
+ }
+ if err == nil {
+ t.Errorf("Expected error to be returned.")
+ }
+ }
+}
+
+func TestMaxPasswordLength(t *testing.T) {
+ type testData struct {
+ input []byte
+ expectedErr error
+
+ // Helper field to output in case of failure; rather than hundreds of
+ // bytes.
+ inputDesc string
+ }
+
+ ds := []testData{
+ testData{append(bytes.Repeat([]byte{'a'}, maxLength), '\n'), nil, fmt.Sprintf("%v 'a' bytes followed by a newline", maxLength)},
+ testData{append(bytes.Repeat([]byte{'a'}, maxLength+1), '\n'), ErrMaxLengthExceeded, fmt.Sprintf("%v 'a' bytes followed by a newline", maxLength+1)},
+ testData{append(bytes.Repeat([]byte{0x00}, maxLength+1), '\n'), ErrMaxLengthExceeded, fmt.Sprintf("%v 0x00 bytes followed by a newline", maxLength+1)},
+ }
+
+ for _, d := range ds {
+ pipeBytesToStdin(d.input)
+ _, err := GetPasswd()
+ if err != d.expectedErr {
+ t.Errorf("Expected error to be %v; isntead got %v from %v", d.expectedErr, err, d.inputDesc)
+ }
+ }
+}
diff --git a/src/github.com/howeyc/gopass/terminal.go b/src/github.com/howeyc/gopass/terminal.go
new file mode 100644
index 0000000..0835641
--- /dev/null
+++ b/src/github.com/howeyc/gopass/terminal.go
@@ -0,0 +1,25 @@
+// +build !solaris
+
+package gopass
+
+import "golang.org/x/crypto/ssh/terminal"
+
+type terminalState struct {
+ state *terminal.State
+}
+
+func isTerminal(fd uintptr) bool {
+ return terminal.IsTerminal(int(fd))
+}
+
+func makeRaw(fd uintptr) (*terminalState, error) {
+ state, err := terminal.MakeRaw(int(fd))
+
+ return &terminalState{
+ state: state,
+ }, err
+}
+
+func restore(fd uintptr, oldState *terminalState) error {
+ return terminal.Restore(int(fd), oldState.state)
+}
diff --git a/src/github.com/howeyc/gopass/terminal_solaris.go b/src/github.com/howeyc/gopass/terminal_solaris.go
new file mode 100644
index 0000000..257e1b4
--- /dev/null
+++ b/src/github.com/howeyc/gopass/terminal_solaris.go
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+// Below is derived from Solaris source, so CDDL license is included.
+
+package gopass
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+type terminalState struct {
+ state *unix.Termios
+}
+
+// isTerminal returns true if there is a terminal attached to the given
+// file descriptor.
+// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
+func isTerminal(fd uintptr) bool {
+ var termio unix.Termio
+ err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
+ return err == nil
+}
+
+// makeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
+func makeRaw(fd uintptr) (*terminalState, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldTermios := *oldTermiosPtr
+
+ newTermios := oldTermios
+ newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL
+ if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil {
+ return nil, err
+ }
+
+ return &terminalState{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+func restore(fd uintptr, oldState *terminalState) error {
+ return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state)
+}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Apr 5, 11:31 PM (42 m, 51 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3188651

Event Timeline