Example #1
0
// Like GosaDecrypt() but operates in-place on buf.
// Returns true if decryption successful and false if not.
// If false is returned, the buffer contents may be destroyed, but only
// if further decryption attempts with other keys would be pointless anyway,
// because of some fatal condition (such as the data not being a multiple of
// the cipher's block size).
func GosaDecryptBuffer(buf *bytes.Buffer, key string) bool {
	buf.TrimSpace()

	if buf.Len() < 11 {
		return false
	} // minimum length of unencrypted <xml></xml>

	data := buf.Bytes()
	if string(data[0:5]) == "<xml>" {
		return true
	}

	// Fixes the following:
	// * gosa-si bug in the following line:
	//     if( $client_answer =~ s/session_id=(\d+)$// ) {
	//   This leaves the "." before "session_id" which breaks base64
	// * new gosa-si protocol has ";IP:PORT" appended to message
	//   which also breaks base64
	for semicolon_period := 0; semicolon_period < len(data); semicolon_period++ {
		if data[semicolon_period] == ';' || data[semicolon_period] == '.' {
			buf.Trim(0, semicolon_period)
			data = buf.Bytes()
			break
		}
	}

	aescipher, _ := aes.NewCipher([]byte(util.Md5sum(key)))
	crypter := cipher.NewCBCDecrypter(aescipher, config.InitializationVector)

	cryptotest := make([]byte, (((3*aes.BlockSize)+2)/3)<<2)
	n := copy(cryptotest, data)
	cryptotest = cryptotest[0:n]
	cryptotest = util.Base64DecodeInPlace(cryptotest)
	n = (len(cryptotest) / aes.BlockSize) * aes.BlockSize
	cryptotest = cryptotest[0:n]
	crypter.CryptBlocks(cryptotest, cryptotest)
	if !strings.Contains(string(cryptotest), "<xml>") {
		return false
	}

	data = util.Base64DecodeInPlace(data)
	buf.Trim(0, len(data))
	data = buf.Bytes()

	if buf.Len()%aes.BlockSize != 0 {
		// this condition is fatal => further decryption attempts are pointless
		buf.Reset()
		return false
	}

	crypter = cipher.NewCBCDecrypter(aescipher, config.InitializationVector)
	crypter.CryptBlocks(data, data)

	buf.TrimSpace() // removes 0 padding, too

	return true
}
Example #2
0
// Returns the base64 representation of the message after encryption with
// the given key. The key is a word as used in gosa-si.conf whose md5sum will
// be used as the actual AES key.
// If msg == "", "" will be returned.
func GosaEncrypt(msg string, key string) string {
	if msg == "" {
		return ""
	}
	aes, _ := aes.NewCipher([]byte(util.Md5sum(key)))
	crypter := cipher.NewCBCEncrypter(aes, config.InitializationVector)
	cyphertext := paddedMessage(msg)
	crypter.CryptBlocks(cyphertext, cyphertext)
	return string(util.Base64EncodeString(string(cyphertext)))
}
Example #3
0
// Replaces the contents of buf with the base64 representation of the data
// after encryption with the given key.
// The key is a word as used in gosa-si.conf whose md5sum will be used as
// the actual AES key. buf is empty, it won't be changed.
func GosaEncryptBuffer(buf *bytes.Buffer, key string) {
	datalen := buf.Len()
	if datalen == 0 {
		return
	}
	ciph, _ := aes.NewCipher([]byte(util.Md5sum(key)))
	crypter := cipher.NewCBCEncrypter(ciph, config.InitializationVector)
	cryptpad := (aes.BlockSize - datalen%aes.BlockSize) &^ aes.BlockSize
	cryptlen := cryptpad + datalen
	b64len := ((cryptlen + 2) / 3) << 2
	for i := datalen; i < b64len; i++ {
		buf.WriteByte(0)
	}
	data := buf.Bytes()
	copy(data[b64len-datalen:], data) // move data back
	idx := b64len - cryptlen
	copy(data[idx:], make([]byte, cryptpad)) // insert 0s in front
	crypter.CryptBlocks(data[idx:], data[idx:])
	util.Base64EncodeInPlace(data, idx)
}
Example #4
0
// Tries to decrypt msg with the given key and returns the decrypted message or
// the empty string if decryption failed. Decryption will be considered successful
// if the decrypted message starts with "<xml>" (after trimming whitespace).
//
// Whitespace will be trimmed at the start and end of msg before decryption.
//
// msg can be one of the following:
//
// * an unencrypted message starting (after trimming) with "<xml>". It will be
// returned trimmed but otherwise unchanged.
//
// * a base64 string as returned by GosaEncrypt when used with the same key.
// The unencrypted message will be returned.
//
// The key is a word as used in gosa-si.conf whose md5sum will
// be used as the actual AES key.
func GosaDecrypt(msg string, key string) string {
	trimmed := strings.TrimSpace(msg)

	if strings.HasPrefix(trimmed, "<xml>") {
		return trimmed
	}

	// Fixes the following:
	// * gosa-si bug in the following line:
	//     if( $client_answer =~ s/session_id=(\d+)$// ) {
	//   This leaves the "." before "session_id" which breaks base64
	// * new gosa-si protocol has ";IP:PORT" appended to message
	//   which also breaks base64
	semicolon_period := strings.IndexAny(trimmed, ";.")
	if semicolon_period >= 0 {
		trimmed = trimmed[:semicolon_period]
	}

	cyphertext := util.Base64DecodeString(trimmed, nil)

	if len(cyphertext)%aes.BlockSize != 0 {
		return ""
	}

	aes, _ := aes.NewCipher([]byte(util.Md5sum(key)))
	crypter := cipher.NewCBCDecrypter(aes, config.InitializationVector)
	crypter.CryptBlocks(cyphertext, cyphertext)

	for len(cyphertext) > 0 && cyphertext[0] == 0 {
		cyphertext = cyphertext[1:]
	}
	for len(cyphertext) > 0 && cyphertext[len(cyphertext)-1] == 0 {
		cyphertext = cyphertext[:len(cyphertext)-1]
	}
	trimmed = strings.TrimSpace(string(cyphertext))
	if strings.HasPrefix(trimmed, "<xml>") {
		return trimmed
	}

	return ""
}
Example #5
0
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/mbenkmann/golib/deque"
	"github.com/mbenkmann/golib/util"
)

// The initialization vector for the AES encryption of GOsa messages.
var InitializationVector = []byte(util.Md5sum("GONICUS GmbH")[0:aes.BlockSize])

// The keys used to address different gosa-si modules.
var ModuleKeys = []string{"dummy-key"}

// Maps a module name surrounded by brackets (such as "[ServerPackages]") to its key.
var ModuleKey = map[string]string{}

// The address to listen on. "127.0.0.1:<port>" listens only for connections from
// the local machine. ":<port>" allows connections from anywhere.
var ServerListenAddress = ":20081"

// IP address part of <source> element.
var IP = "127.0.0.1"

// If this is true, go-susi will offer server functionality in addition