summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2016-01-14 09:08:13 -0600
committer=Corey Hulen <corey@hulen.com>2016-01-14 09:08:13 -0600
commit6d6cada0970a2b341f36dac9b0fed8262ada1865 (patch)
treefc3728f15deaebd0c870838a63735659a33456e7 /utils
parent0b986ed3147c885af6b2f33e1ff3eb6754e8f274 (diff)
parenta341dbad2b8a4564b6f270c79f2f9932e499ac80 (diff)
downloadchat-6d6cada0970a2b341f36dac9b0fed8262ada1865.tar.gz
chat-6d6cada0970a2b341f36dac9b0fed8262ada1865.tar.bz2
chat-6d6cada0970a2b341f36dac9b0fed8262ada1865.zip
Merge branch 'master' into PLT-1429
Diffstat (limited to 'utils')
-rw-r--r--utils/config.go6
-rw-r--r--utils/license.go157
-rw-r--r--utils/license_test.go50
-rw-r--r--utils/mail.go2
4 files changed, 212 insertions, 3 deletions
diff --git a/utils/config.go b/utils/config.go
index 1e6b58ced..024c28d16 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -11,7 +11,7 @@ import (
"path/filepath"
"strconv"
- l4g "code.google.com/p/log4go"
+ l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
)
@@ -77,7 +77,9 @@ func configureLog(s *model.LogSettings) {
level = l4g.ERROR
}
- l4g.AddFilter("stdout", level, l4g.NewConsoleLogWriter())
+ lw := l4g.NewConsoleLogWriter()
+ lw.SetFormat("[%D %T] [%L] %M")
+ l4g.AddFilter("stdout", level, lw)
}
if s.EnableFile {
diff --git a/utils/license.go b/utils/license.go
new file mode 100644
index 000000000..7594e33af
--- /dev/null
+++ b/utils/license.go
@@ -0,0 +1,157 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package utils
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/rsa"
+ "crypto/sha512"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/pem"
+ "io"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ l4g "github.com/alecthomas/log4go"
+
+ "github.com/mattermost/platform/model"
+)
+
+const (
+ LICENSE_FILENAME = "active.dat"
+)
+
+var IsLicensed bool = false
+var License *model.License = &model.License{}
+var ClientLicense map[string]string = make(map[string]string)
+
+// test public key
+var publicKey []byte = []byte(`-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3/k3Al9q1Xe+xngQ/yGn
+0suaJopea3Cpf6NjIHdO8sYTwLlxqt0Mdb+qBR9LbCjZfcNmqc5mZONvsyCEoN/5
+VoLdlv1m9ao2BSAWphUxE2CPdUWdLOsDbQWliSc5//UhiYeR+67Xxon0Hg0LKXF6
+PumRIWQenRHJWqlUQZ147e7/1v9ySVRZksKpvlmMDzgq+kCH/uyM1uVP3z7YXhlN
+K7vSSQYbt4cghvWQxDZFwpLlsChoY+mmzClgq+Yv6FLhj4/lk94twdOZau/AeZFJ
+NxpC+5KFhU+xSeeklNqwCgnlOyZ7qSTxmdJHb+60SwuYnnGIYzLJhY4LYDr4J+KR
+1wIDAQAB
+-----END PUBLIC KEY-----`)
+
+func LoadLicense() {
+ file, err := os.Open(LicenseLocation())
+ if err != nil {
+ l4g.Warn("Unable to open/find license file")
+ return
+ }
+ defer file.Close()
+
+ buf := bytes.NewBuffer(nil)
+ io.Copy(buf, file)
+
+ if success, licenseStr := ValidateLicense(buf.Bytes()); success {
+ license := model.LicenseFromJson(strings.NewReader(licenseStr))
+ SetLicense(license)
+ }
+
+ l4g.Warn("No valid enterprise license found")
+}
+
+func SetLicense(license *model.License) bool {
+ license.Features.SetDefaults()
+
+ if !license.IsExpired() && license.IsStarted() {
+ License = license
+ IsLicensed = true
+ ClientLicense = getClientLicense(license)
+ return true
+ }
+
+ return false
+}
+
+func LicenseLocation() string {
+ return filepath.Dir(CfgFileName) + "/" + LICENSE_FILENAME
+}
+
+func RemoveLicense() bool {
+ License = &model.License{}
+ IsLicensed = false
+ ClientLicense = getClientLicense(License)
+
+ if err := os.Remove(LicenseLocation()); err != nil {
+ l4g.Error("Unable to remove license file, err=%v", err.Error())
+ return false
+ }
+
+ return true
+}
+
+func ValidateLicense(signed []byte) (bool, string) {
+ decoded := make([]byte, base64.StdEncoding.DecodedLen(len(signed)))
+
+ _, err := base64.StdEncoding.Decode(decoded, signed)
+ if err != nil {
+ l4g.Error("Encountered error decoding license, err=%v", err.Error())
+ return false, ""
+ }
+
+ if len(decoded) <= 256 {
+ l4g.Error("Signed license not long enough")
+ return false, ""
+ }
+
+ // remove null terminator
+ if decoded[len(decoded)-1] == byte(0) {
+ decoded = decoded[:len(decoded)-1]
+ }
+
+ plaintext := decoded[:len(decoded)-256]
+ signature := decoded[len(decoded)-256:]
+
+ block, _ := pem.Decode(publicKey)
+
+ public, err := x509.ParsePKIXPublicKey(block.Bytes)
+ if err != nil {
+ l4g.Error("Encountered error signing license, err=%v", err.Error())
+ return false, ""
+ }
+
+ rsaPublic := public.(*rsa.PublicKey)
+
+ h := sha512.New()
+ h.Write(plaintext)
+ d := h.Sum(nil)
+
+ err = rsa.VerifyPKCS1v15(rsaPublic, crypto.SHA512, d, signature)
+ if err != nil {
+ l4g.Error("Invalid signature, err=%v", err.Error())
+ return false, ""
+ }
+
+ return true, string(plaintext)
+}
+
+func getClientLicense(l *model.License) map[string]string {
+ props := make(map[string]string)
+
+ props["IsLicensed"] = strconv.FormatBool(IsLicensed)
+
+ if IsLicensed {
+ props["Users"] = strconv.Itoa(*l.Features.Users)
+ props["LDAP"] = strconv.FormatBool(*l.Features.LDAP)
+ props["GoogleSSO"] = strconv.FormatBool(*l.Features.GoogleSSO)
+ props["IssuedAt"] = strconv.FormatInt(l.IssuedAt, 10)
+ props["StartsAt"] = strconv.FormatInt(l.StartsAt, 10)
+ props["ExpiresAt"] = strconv.FormatInt(l.ExpiresAt, 10)
+ props["Name"] = l.Customer.Name
+ props["Email"] = l.Customer.Email
+ props["Company"] = l.Customer.Company
+ props["PhoneNumber"] = l.Customer.PhoneNumber
+ }
+
+ return props
+}
diff --git a/utils/license_test.go b/utils/license_test.go
new file mode 100644
index 000000000..826107032
--- /dev/null
+++ b/utils/license_test.go
@@ -0,0 +1,50 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package utils
+
+import (
+ "github.com/mattermost/platform/model"
+ "testing"
+)
+
+func TestSetLicense(t *testing.T) {
+ l1 := &model.License{}
+ l1.Features = &model.Features{}
+ l1.Customer = &model.Customer{}
+ l1.StartsAt = model.GetMillis() - 1000
+ l1.ExpiresAt = model.GetMillis() + 100000
+ if ok := SetLicense(l1); !ok {
+ t.Fatal("license should have worked")
+ }
+
+ l2 := &model.License{}
+ l2.Features = &model.Features{}
+ l2.Customer = &model.Customer{}
+ l2.StartsAt = model.GetMillis() - 1000
+ l2.ExpiresAt = model.GetMillis() - 100
+ if ok := SetLicense(l2); ok {
+ t.Fatal("license should have failed")
+ }
+
+ l3 := &model.License{}
+ l3.Features = &model.Features{}
+ l3.Customer = &model.Customer{}
+ l3.StartsAt = model.GetMillis() + 10000
+ l3.ExpiresAt = model.GetMillis() + 100000
+ if ok := SetLicense(l3); ok {
+ t.Fatal("license should have failed")
+ }
+}
+
+func TestValidateLicense(t *testing.T) {
+ b1 := []byte("junk")
+ if ok, _ := ValidateLicense(b1); ok {
+ t.Fatal("should have failed - bad license")
+ }
+
+ b2 := []byte("junkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunk")
+ if ok, _ := ValidateLicense(b2); ok {
+ t.Fatal("should have failed - bad license")
+ }
+}
diff --git a/utils/mail.go b/utils/mail.go
index 6625060de..2f2c10b61 100644
--- a/utils/mail.go
+++ b/utils/mail.go
@@ -4,10 +4,10 @@
package utils
import (
- l4g "code.google.com/p/log4go"
"crypto/tls"
"encoding/base64"
"fmt"
+ l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
"net"
"net/mail"