Skip to content

Commit

Permalink
First version of ident which passes a crude test.
Browse files Browse the repository at this point in the history
  • Loading branch information
jlouis committed May 10, 2010
1 parent 453762f commit e6240a9
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 14 deletions.
35 changes: 21 additions & 14 deletions ident.go
Expand Up @@ -23,6 +23,8 @@ type ProtocolError struct {
}

type IdentResponse struct {
ServerPort int
ClientPort int
ResponseTy string // The type of response, "ERROR", or "USERID"
Error string // Is either an identd error message or ""
UserId []byte // The Id of the user.
Expand Down Expand Up @@ -106,11 +108,12 @@ func parsePorts(l []byte) (int, int, os.Error) {
if len(bs) < 2 {
return 0, 0, &badStringError{"Could not parse ports", string(l)}
}
sPort, e1 := strconv.Atoi(strings.TrimSpace(string(bs[0])))
// TODO: These slice expresssions ought to be improved
sPort, e1 := strconv.Atoi(strings.TrimSpace(string(bs[0][0 : len(bs[0])-1])))
if e1 != nil {
return 0, 0, e1
}
dPort, e2 := strconv.Atoi(strings.TrimSpace(string(bs[1])))
dPort, e2 := strconv.Atoi(strings.TrimSpace(string(bs[1][0 : len(bs[1])-1])))
if e2 != nil {
return 0, 0, e2
}
Expand Down Expand Up @@ -190,7 +193,8 @@ func parseUserIdAddInfo(r *IdentResponse, ai []byte) (*IdentResponse, os.Error)

opsysCharset := bytes.SplitAfter(ais[0], comma, 0)
if len(opsysCharset) == 2 {
switch strings.TrimSpace(string(opsysCharset[1])) {
cs := string(opsysCharset[1][0 : len(opsysCharset[1])-1])
switch strings.TrimSpace(cs) {
case "ASCII-US":
r.Charset = "ASCII-US"
default:
Expand All @@ -199,7 +203,8 @@ func parseUserIdAddInfo(r *IdentResponse, ai []byte) (*IdentResponse, os.Error)
}

if len(opsysCharset) >= 1 {
switch strings.TrimSpace(string(opsysCharset[0])) {
os := string(opsysCharset[0][0 : len(opsysCharset[0])-1])
switch strings.TrimSpace(os) {
case "UNIX":
r.OperatingSystem = "UNIX"
case "OTHER":
Expand Down Expand Up @@ -232,7 +237,7 @@ func parseUserIdAddInfo(r *IdentResponse, ai []byte) (*IdentResponse, os.Error)
// Parse the type and addInfo sections into an IdentResponse.
func parseType(l []byte, addInfo []byte) (*IdentResponse, os.Error) {
r := new(IdentResponse)
s := strings.TrimSpace(string(l))
s := strings.TrimSpace(string(l[0 : len(l)-1]))
switch s {
case "USERID":
r.ResponseTy = "USERID"
Expand All @@ -249,25 +254,27 @@ func parseType(l []byte, addInfo []byte) (*IdentResponse, os.Error) {
return r, nil
}

func ParseResponse(l []byte) (int, int, *IdentResponse, os.Error) {
func ParseResponse(l []byte) (*IdentResponse, os.Error) {
bs := bytes.SplitAfter(l, colon, 3)
if len(bs) < 3 {
goto Malformed
}
sPort, cPort, e := parsePorts(bs[0])
if e != nil {
return 0, 0, nil, e
return nil, e
}

respTy, e2 := parseType(bs[1], bs[2])
r, e2 := parseType(bs[1], bs[2])
if e2 != nil {
return 0, 0, nil, e2
return nil, e2
}

return sPort, cPort, respTy, nil
r.ServerPort = sPort
r.ClientPort = cPort
return r, nil

Malformed:
return 0, 0, nil, &badStringError{"Malformed ident parse", string(l)}
return nil, &badStringError{"Malformed ident parse", string(l)}
}

// Make a connection to host asking for an iden on the server port sPort and client port cPort.
Expand All @@ -278,10 +285,10 @@ Malformed:
//
// The function returns the source port reflected on the server, the destination port reflected
// on the server and an IdentResponse struct containing the ident information.
func Identify(hostname string, sPort int, cPort int) (int, int, *IdentResponse, os.Error) {
func Identify(hostname string, sPort int, cPort int) (*IdentResponse, os.Error) {
conn, err1 := net.Dial("tcp", "", hostname+":"+string(identPort))
if err1 != nil {
return 0, 0, nil, err1
return nil, err1
}
defer conn.Close()

Expand All @@ -290,7 +297,7 @@ func Identify(hostname string, sPort int, cPort int) (int, int, *IdentResponse,
r := bufio.NewReader(conn)
response, err2 := readLineBytes(r)
if err2 != nil {
return 0, 0, nil, err2
return nil, err2
}

return ParseResponse(response)
Expand Down
35 changes: 35 additions & 0 deletions ident_test.go
@@ -0,0 +1,35 @@
// Tests for ident.go

package ident

import (
"testing"
)

type parseResponseTest struct {
query string
valid bool
error bool
}

var parseResponseTests = []parseResponseTest{
parseResponseTest{query: "6113,23:USERID:UNIX:joe", valid: true, error: false},
parseResponseTest{query: "6113,23:ERROR:NO-USER", valid: false, error: false},
}

func TestParseResponse(t *testing.T) {
for i, test := range parseResponseTests {
q, err := ParseResponse([]byte(test.query))
if !test.error && err != nil {
t.Errorf("test %d: Unexpected error: %v", i, err)
}
if test.error && err == nil {
t.Errorf("test %d should have returned error", i)
}
if q != nil && q.Valid != test.valid {
t.Errorf("test %d does not agree on validity", i)
}
}
}

// vim: set ft=go noexpandtab sw=8 sts=8

0 comments on commit e6240a9

Please sign in to comment.