mirror of https://github.com/grafana/grafana
Fixed hashing of passwords, Closes #3
parent
6d814af0cc
commit
3226a3a58e
@ -1 +1 @@ |
||||
Subproject commit d3e11cabd51d082244f83258b02fd635cc780c08 |
||||
Subproject commit 164435f71d3462fa1719791e1c8eb9841374d299 |
||||
@ -0,0 +1,45 @@ |
||||
package api |
||||
|
||||
import ( |
||||
"regexp" |
||||
"strings" |
||||
|
||||
"github.com/torkelo/grafana-pro/pkg/bus" |
||||
"github.com/torkelo/grafana-pro/pkg/middleware" |
||||
m "github.com/torkelo/grafana-pro/pkg/models" |
||||
) |
||||
|
||||
func Search(c *middleware.Context) { |
||||
queryText := c.Query("q") |
||||
result := m.SearchResult{ |
||||
Dashboards: []*m.DashboardSearchHit{}, |
||||
Tags: []*m.DashboardTagCloudItem{}, |
||||
} |
||||
|
||||
if strings.HasPrefix(queryText, "tags!:") { |
||||
query := m.GetDashboardTagsQuery{} |
||||
err := bus.Dispatch(&query) |
||||
if err != nil { |
||||
c.JsonApiErr(500, "Failed to get tags from database", err) |
||||
return |
||||
} |
||||
result.Tags = query.Result |
||||
result.TagsOnly = true |
||||
} else { |
||||
searchQueryRegEx, _ := regexp.Compile(`(tags:(\w*)\sAND\s)?(?:title:)?(.*)?`) |
||||
matches := searchQueryRegEx.FindStringSubmatch(queryText) |
||||
query := m.SearchDashboardsQuery{ |
||||
Title: matches[3], |
||||
Tag: matches[2], |
||||
AccountId: c.GetAccountId(), |
||||
} |
||||
err := bus.Dispatch(&query) |
||||
if err != nil { |
||||
c.JsonApiErr(500, "Search failed", err) |
||||
return |
||||
} |
||||
result.Dashboards = query.Result |
||||
} |
||||
|
||||
c.JSON(200, result) |
||||
} |
||||
@ -0,0 +1,67 @@ |
||||
package util |
||||
|
||||
import ( |
||||
"crypto/hmac" |
||||
"crypto/rand" |
||||
"crypto/sha256" |
||||
"fmt" |
||||
"hash" |
||||
) |
||||
|
||||
// source: https://github.com/gogits/gogs/blob/9ee80e3e5426821f03a4e99fad34418f5c736413/modules/base/tool.go#L58
|
||||
func GetRandomString(n int, alphabets ...byte) string { |
||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" |
||||
var bytes = make([]byte, n) |
||||
rand.Read(bytes) |
||||
for i, b := range bytes { |
||||
if len(alphabets) == 0 { |
||||
bytes[i] = alphanum[b%byte(len(alphanum))] |
||||
} else { |
||||
bytes[i] = alphabets[b%byte(len(alphabets))] |
||||
} |
||||
} |
||||
return string(bytes) |
||||
} |
||||
|
||||
func EncodePassword(password string, salt string) string { |
||||
newPasswd := PBKDF2([]byte(password), []byte(salt), 10000, 50, sha256.New) |
||||
return fmt.Sprintf("%x", newPasswd) |
||||
} |
||||
|
||||
// http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto
|
||||
func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { |
||||
prf := hmac.New(h, password) |
||||
hashLen := prf.Size() |
||||
numBlocks := (keyLen + hashLen - 1) / hashLen |
||||
|
||||
var buf [4]byte |
||||
dk := make([]byte, 0, numBlocks*hashLen) |
||||
U := make([]byte, hashLen) |
||||
for block := 1; block <= numBlocks; block++ { |
||||
// N.B.: || means concatenation, ^ means XOR
|
||||
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
||||
// U_1 = PRF(password, salt || uint(i))
|
||||
prf.Reset() |
||||
prf.Write(salt) |
||||
buf[0] = byte(block >> 24) |
||||
buf[1] = byte(block >> 16) |
||||
buf[2] = byte(block >> 8) |
||||
buf[3] = byte(block) |
||||
prf.Write(buf[:4]) |
||||
dk = prf.Sum(dk) |
||||
T := dk[len(dk)-hashLen:] |
||||
copy(U, T) |
||||
|
||||
// U_n = PRF(password, U_(n-1))
|
||||
for n := 2; n <= iter; n++ { |
||||
prf.Reset() |
||||
prf.Write(U) |
||||
U = U[:0] |
||||
U = prf.Sum(U) |
||||
for x := range U { |
||||
T[x] ^= U[x] |
||||
} |
||||
} |
||||
} |
||||
return dk[:keyLen] |
||||
} |
||||
@ -1,3 +1,3 @@ |
||||
package utils |
||||
package util |
||||
|
||||
type DynMap map[string]interface{} |
||||
@ -1,4 +1,4 @@ |
||||
package utils |
||||
package util |
||||
|
||||
import ( |
||||
"net/url" |
||||
Loading…
Reference in new issue