Skip to content

Commit 7e4b290

Browse files
committed
Add Memcached Authentication Support
Signed-off-by: Muhammad Raisul Islam Evan <raisul@appscode.com>
1 parent ae2365e commit 7e4b290

2 files changed

Lines changed: 118 additions & 1 deletion

File tree

.idea/workspace.xml

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

memcache/memcache.go

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ var (
6262

6363
// ErrNoServers is returned when no servers are configured or available.
6464
ErrNoServers = errors.New("memcache: no servers configured or available")
65+
66+
// ErrNotAuthenticated is returned when Client Authentication failed due to any reason.
67+
ErrNotAuthenticated = errors.New("memcache: Client Authentication Failed")
6568
)
6669

6770
const (
@@ -114,6 +117,13 @@ var (
114117

115118
resultClientErrorPrefix = []byte("CLIENT_ERROR ")
116119
versionPrefix = []byte("VERSION")
120+
121+
// Authentication Related Error
122+
resultUnauthenticatedError = []byte("CLIENT_ERROR unauthenticated\r\n")
123+
resultAuthenticationFailure = []byte("CLIENT_ERROR authentication failure\r\n")
124+
resultBadCommandFormat = []byte("CLIENT_ERROR bad command line format\r\n")
125+
resultBadCommandFormatTermination = []byte("CLIENT_ERROR bad command line format termination\r\n")
126+
resultBadAuthenticationTokenFormat = []byte("CLIENT_ERROR bad authentication token format\r\n")
117127
)
118128

119129
// New returns a memcache client using the provided server(s)
@@ -181,6 +191,12 @@ type Item struct {
181191
// It's populated by get requests and then the same value is
182192
// required for a CompareAndSwap request to succeed.
183193
CasID uint64
194+
195+
// Username for Authentication
196+
User string
197+
198+
// Password for Authentication
199+
Pass string
184200
}
185201

186202
// conn is a connection to a server.
@@ -320,7 +336,7 @@ func (c *Client) onItem(item *Item, fn func(*Client, *bufio.ReadWriter, *Item) e
320336
return err
321337
}
322338
defer cn.condRelease(&err)
323-
if err = fn(c, cn.rw, item); err != nil {
339+
if err := fn(c, cn.rw, item); err != nil {
324340
return err
325341
}
326342
return nil
@@ -847,3 +863,48 @@ func (c *Client) Close() error {
847863
c.freeconn = nil
848864
return ret
849865
}
866+
867+
// Memcached Authentication Support
868+
869+
func (c *Client) SetAuth(item *Item) error {
870+
return c.onItem(item, (*Client).setAuth)
871+
}
872+
873+
func (c *Client) setAuth(rw *bufio.ReadWriter, item *Item) error {
874+
return c.authFunc(rw, "set", item)
875+
}
876+
877+
func (c *Client) authFunc(rw *bufio.ReadWriter, verb string, item *Item) error {
878+
if !legalKey(item.Key) {
879+
return ErrMalformedKey
880+
}
881+
var err error
882+
_, err = fmt.Fprintf(rw, "%s %s %d %d %d\r\n%s %s\r\n",
883+
verb, item.Key, item.Flags, item.Expiration, len(item.User)+len(item.Pass)+1, item.User, item.Pass)
884+
if err != nil {
885+
return err
886+
}
887+
if err := rw.Flush(); err != nil {
888+
return err
889+
}
890+
line, err := rw.ReadSlice('\n')
891+
892+
if err != nil {
893+
return err
894+
}
895+
switch {
896+
case bytes.Equal(line, resultStored):
897+
return nil
898+
case bytes.Equal(line, resultUnauthenticatedError):
899+
return ErrNotAuthenticated
900+
case bytes.Equal(line, resultAuthenticationFailure):
901+
return ErrNotAuthenticated
902+
case bytes.Equal(line, resultBadCommandFormat):
903+
return ErrNotAuthenticated
904+
case bytes.Equal(line, resultBadCommandFormatTermination):
905+
return ErrNotAuthenticated
906+
case bytes.Equal(line, resultBadAuthenticationTokenFormat):
907+
return ErrNotAuthenticated
908+
}
909+
return fmt.Errorf("memcache: unexpected response line from %q: %q", verb, string(line))
910+
}

0 commit comments

Comments
 (0)