Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quoted passwords #13

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src-tests/data/test6a.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password """"
1 change: 1 addition & 0 deletions src-tests/data/test6a.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6a.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc
1 change: 1 addition & 0 deletions src-tests/data/test6b.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""multi-word password""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be "multi-word password", like a string in double-quotes?
Now it is double double-quotes...

1 change: 1 addition & 0 deletions src-tests/data/test6b.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "multi-word password", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6b.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""multi-word password""
1 change: 1 addition & 0 deletions src-tests/data/test6c.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""unescape \\ backslash""
1 change: 1 addition & 0 deletions src-tests/data/test6c.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "unescape \\ backslash", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6c.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""unescape \\ backslash""
1 change: 1 addition & 0 deletions src-tests/data/test6d.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""unescape \" quote""
1 change: 1 addition & 0 deletions src-tests/data/test6d.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "unescape \" quote", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6d.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""unescape \" quote""
1 change: 1 addition & 0 deletions src-tests/data/test6e.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""unclosed-double-quotes
1 change: 1 addition & 0 deletions src-tests/data/test6e.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "\"\"unclosed-double-quotes", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6e.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""unclosed-double-quotes
1 change: 1 addition & 0 deletions src-tests/data/test6f.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""password with # comment""
1 change: 1 addition & 0 deletions src-tests/data/test6f.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "password with # comment", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6f.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password ""password with # comment""
1 change: 1 addition & 0 deletions src-tests/data/test6g.netrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password "single # quote should be treated as normal password"
1 change: 1 addition & 0 deletions src-tests/data/test6g.netrc.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Right (NetRc {nrHosts = [NetRcHost {nrhName = "", nrhLogin = "abc", nrhPassword = "\"single", nrhAccount = "", nrhMacros = []}], nrMacros = []})
1 change: 1 addition & 0 deletions src-tests/data/test6g.netrc.out2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default login abc password "single
33 changes: 31 additions & 2 deletions src/Network/NetRc.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
-- and after @machine@\/@default@\/@macdef@ entries. Be aware though
-- that such @#@-comment are not supported by all @.netrc@-aware
-- applications, including @ftp(1)@.
--
-- Passwords can contain spaces only if they are double-quoted, in which
-- case backslashes and quotes are to be escaped with a preceding backslash.

module Network.NetRc
( -- * Types
NetRc(..)
Expand Down Expand Up @@ -128,7 +132,19 @@ netRcToBuilder (NetRc ms ds) =
| otherwise = BB.byteString "machine" <> spc <> BB.byteString nrhName

prop lab val | B.null val = mempty
| otherwise = spc <> BB.byteString lab <> spc <> BB.byteString val
| otherwise = spc <> BB.byteString lab <> spc <> valString lab val

valString "password" val
| BC.elem ' ' val || BC.elem '\t' val
= BB.byteString "\"\""
<> BB.byteString (BC.concatMap (BC.pack . escape) val)
<> BB.byteString "\"\""
| otherwise = BB.byteString val
where
escape '\\' = "\\\\"
escape '\"' = "\\\""
escape x = [ x ]
valString _ val = BB.byteString val

netRcMacDefToBuilder (NetRcMacDef {..})
= BB.byteString "macdef" <> spc <> BB.byteString nrmName <>
Expand Down Expand Up @@ -238,10 +254,14 @@ hostEnt = do
-- pval := ((account|username|password) WS+ <value>)
pval = hlp "login" PValLogin <|>
hlp "account" PValAccount <|>
hlp "password" PValPassword
hlpPassword
where
hlp tnam cons = P.try (P.string tnam) *> wsChars1 *>
(cons <$> tok P.<?> (tnam ++ "-value"))
hlpPassword = P.try (P.string "password") *> wsChars1 *>
(PValPassword <$> password P.<?> "password-value")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to parametrize hlp by the parser (tok or password) rather than duplicating it into hlpPassword?

password = P.try quotedPassword <|> tok


setFld n (PValLogin v) = n { nrhLogin = v }
setFld n (PValAccount v) = n { nrhAccount = v }
Expand All @@ -250,6 +270,14 @@ hostEnt = do
tok :: P.Parser ByteString
tok = BC.pack <$> P.many1 notWsChar P.<?> "token"

quotedPassword :: P.Parser ByteString
quotedPassword = do
BC.pack <$> (P.string "\"\"" *> P.many chars <* P.string "\"\"")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thing this should be (P.string "\"" *> P.many chars <* P.string "\"").

where
chars = escaped <|> P.noneOf "\""
escaped = P.char '\\' >> P.choice [ P.char '\\' >> return '\\'
, P.char '"' >> return '"' ]

data PVal = PValLogin !ByteString
| PValAccount !ByteString
| PValPassword !ByteString
Expand Down Expand Up @@ -288,3 +316,4 @@ splitEithers = goL
isLeft (Right _) = False

isRight = not . isLeft