Beispiel #1
0
// Runs this Hash's text child through a base64 encoder and replaces it with
// the result.
func (self *Hash) EncodeBase64() {
	text := self.TextFragments()
	self.SetText()
	carry := make([]byte, 0, 2)
	for i := range text {
		l := len(text[i]) + len(carry)
		var rem int
		var buf []byte
		if i < len(text)-1 { // if we have a next string that we can carry over into
			rem = l % 3 // round down l to multiple of 3 and carry over the remainder
			l -= rem
			if l == 0 { // nothing remaining? carry over everything
				carry = append(carry, text[i]...)
				continue
			}
			buf = make([]byte, (l/3)<<2)
		} else { // last string, can't carry over
			buf = make([]byte, ((l+2)/3)<<2)
		}
		idx := len(buf) - l
		copy(buf[idx:], carry)
		copy(buf[idx+len(carry):], text[i])
		carry = append(carry[0:0], text[i][len(text[i])-rem:]...)
		self.AppendString(string(util.Base64EncodeInPlace(buf, idx)))
	}
}
Beispiel #2
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)
}
// Handles the message "gosa_get_log_file_by_date_and_mac".
//  xmlmsg: the decrypted and parsed message
// Returns:
//  unencrypted reply
func gosa_get_log_file_by_date_and_mac(xmlmsg *xml.Hash) *xml.Hash {
	macaddress := xmlmsg.Text("mac")
	lmac := strings.ToLower(macaddress)
	subdir := xmlmsg.Text("date")
	log_file := xmlmsg.Text("log_file")

	header := "get_log_file_by_date_and_mac"
	x := xml.NewHash("xml", "header", header)
	x.Add(header)
	x.Add("source", config.ServerSourceAddress)
	x.Add("target", "GOSA")
	x.Add("session_id", "1")

	if !macAddressRegexp.MatchString(macaddress) {
		emsg := fmt.Sprintf("Illegal or missing <mac> element in message: %v", xmlmsg)
		util.Log(0, "ERROR! %v", emsg)
		return ErrorReplyXML(emsg)
	}

	// As a precaution, make sure subdir and log_file contain no slashes.
	subdir = strings.Replace(subdir, "/", "_", -1)
	log_file = strings.Replace(log_file, "/", "_", -1)

	if subdir == "" {
		// When you open the installation logs in GOsa for the first time, GOsa sends
		// a broken request that is characterized by an empty <date> and log_file==0.
		// If we return an error, GOsa presents it to the user which
		// gives a bad experience. So we instead return an empty reply in this special case.
		if log_file == "0" {
			return x
		}
		emsg := fmt.Sprintf("Missing or empty <date> element in message: %v", xmlmsg)
		util.Log(0, "ERROR! %v", emsg)
		return ErrorReplyXML(emsg)
	}

	if log_file == "" {
		emsg := fmt.Sprintf("Missing or empty <log_file> element in message: %v", xmlmsg)
		util.Log(0, "ERROR! %v", emsg)
		return ErrorReplyXML(emsg)
	}

	f, err := os.Open(path.Join(config.FAILogPath, lmac, subdir, log_file))
	if err != nil {
		emsg := fmt.Sprintf("gosa_get_log_file_by_date_and_mac: %v", err)
		util.Log(0, "ERROR! %v", emsg)
		return ErrorReplyXML(emsg)
	}
	defer f.Close()

	var b bytes.Buffer
	defer b.Reset()
	buffy := make([]byte, 65536)
	for {
		n, err := f.Read(buffy)
		b.Write(buffy[0:n])
		if err == io.EOF {
			break
		}
		if err != nil {
			emsg := fmt.Sprintf("gosa_get_log_file_by_date_and_mac: %v", err)
			util.Log(0, "ERROR! %v", emsg)
			return ErrorReplyXML(emsg)
		}
		if n == 0 {
			util.Log(0, "WARNING! Read returned 0 bytes but no error. Assuming EOF")
			break
		}
	}

	idx := (((b.Len() + 2) / 3) << 2) - b.Len()
	b.Write0(idx)
	data := b.Bytes()
	copy(data[idx:], data)
	data = util.Base64EncodeInPlace(data, idx)

	data_element := x.Add(log_file)

	// To reduce memory leak potential, we append in pieces rather than as one large string
	end := xml.MaxFragmentLength
	for ; end < len(data); end += xml.MaxFragmentLength {
		data_element.AppendString(string(data[end-xml.MaxFragmentLength : end]))
	}
	data_element.AppendString(string(data[end-xml.MaxFragmentLength:]))

	return x
}
Beispiel #4
0
func testBase64() {
	check(util.Base64DecodeString("", nil), []byte{})
	check(util.Base64DecodeInPlace([]byte{}), []byte{})
	check(util.Base64DecodeString("=", nil), []byte{})
	check(util.Base64DecodeInPlace([]byte("=")), []byte{})
	check(util.Base64DecodeString("  =  ", nil), []byte{})
	check(util.Base64DecodeInPlace([]byte("  =  ")), []byte{})
	check(util.Base64DecodeString("/+/+", nil), []byte{0xff, 0xef, 0xfe})
	check(util.Base64DecodeInPlace([]byte("/+/+")), []byte{0xff, 0xef, 0xfe})
	check(util.Base64DecodeString("_-_-", nil), []byte{0xff, 0xef, 0xfe})
	check(util.Base64DecodeInPlace([]byte("_-_-")), []byte{0xff, 0xef, 0xfe})
	var devnull int
	check(string(util.Base64DecodeString("SGFsbG8=", nil)), "Hallo")
	check(string(util.Base64DecodeInPlace([]byte("SGFsbG8="))), "Hallo")
	check(string(util.Base64DecodeString("SGFsbA==", nil)), "Hall")
	check(string(util.Base64DecodeInPlace([]byte("SGFsbA=="))), "Hall")
	check(string(util.Base64DecodeString("SGFsbG8", nil)), "Hallo")
	check(string(util.Base64DecodeInPlace([]byte("SGFsbG8"))), "Hallo")
	check(string(util.Base64DecodeString("SGFsbA=", nil)), "Hall")
	check(string(util.Base64DecodeInPlace([]byte("SGFsbA="))), "Hall")
	check(string(util.Base64DecodeString("SGFsbG8===", nil)), "Hallo")
	check(string(util.Base64DecodeInPlace([]byte("SGFsbG8==="))), "Hallo")
	check(string(util.Base64DecodeString("SGFsbA", nil)), "Hall")
	check(string(util.Base64DecodeInPlace([]byte("SGFsbA"))), "Hall")
	check(string(util.Base64DecodeString("SGFsbG8=", &devnull)), "Hallo")
	check(devnull, 0)
	check(string(util.Base64DecodeString("SGFsbA==", &devnull)), "Hall")
	check(devnull, 0)
	check(string(util.Base64DecodeString("SGFsbA=", &devnull)), "Hall")
	check(devnull, 0)
	check(string(util.Base64DecodeString("SGFsbG8===", &devnull)), "Hallo")
	check(devnull, 0)
	check(string(util.Base64DecodeString("AA", nil)), "\000")
	check(string(util.Base64DecodeInPlace([]byte("AA"))), "\000")
	check(string(util.Base64DecodeString("AAA", nil)), "\000\000")
	check(string(util.Base64DecodeInPlace([]byte("AAA"))), "\000\000")
	var zerocarry int
	check(string(util.Base64DecodeString("AA", &zerocarry)), "")
	check(zerocarry != 0, true)
	check(string(util.Base64DecodeString("=", &zerocarry)), "\000")
	check(zerocarry, 0)
	check(string(util.Base64DecodeString("AAA", &zerocarry)), "")
	check(zerocarry != 0, true)
	check(string(util.Base64DecodeString("=", &zerocarry)), "\000\000")
	check(zerocarry, 0)

	testbuf := make([]byte, 1024)
	for i := range testbuf {
		testbuf[i] = byte(i)
	}

	error_list := ""
	for length := 0; length <= 12; length++ {
		for eq := 0; eq <= 4; eq++ {
			for err := 0; err <= 12; err++ {
				b64_1 := base64.StdEncoding.EncodeToString(testbuf[0 : 512-length])

				testslice := b64_1[0:]
				errors := []int{0}
				for e := 0; e < err; e++ {
					errors = append(errors, errors[e]+rand.Intn(len(testslice)-errors[e]))
				}
				errors = append(errors, len(testslice))
				teststr := ""
				for i := 0; i < len(errors)-1; i++ {
					if i != 0 {
						teststr = teststr + "\000\n"
					}
					teststr = teststr + testslice[errors[i]:errors[i+1]]
				}

				for i := 0; i < eq; i++ {
					teststr += "="
				}
				// because we're concatenating we need at least 1 "=" if the
				// first string ends in an incomplete block
				if eq == 0 && (length&3) != 0 {
					teststr += "="
				}

				b64_2 := base64.URLEncoding.EncodeToString(testbuf[512-length:])

				testslice = b64_2[0:]
				errors = []int{0}
				for e := 0; e < err; e++ {
					errors = append(errors, errors[e]+rand.Intn(len(testslice)-errors[e]))
				}
				errors = append(errors, len(testslice))
				for i := 0; i < len(errors)-1; i++ {
					if i != 0 {
						teststr = teststr + " "
					}
					teststr = teststr + testslice[errors[i]:errors[i+1]]
				}

				for i := 0; i < eq; i++ {
					teststr += "="
				}

				for parts := 0; parts < 5; parts++ {
					stops := []int{0}
					for e := 0; e < parts; e++ {
						stops = append(stops, stops[e]+rand.Intn(len(teststr)-stops[e]))
					}
					stops = append(stops, len(teststr))

					decoded := ""
					carry := 0
					for i := 0; i < len(stops)-1; i++ {
						decoded += string(util.Base64DecodeString(teststr[stops[i]:stops[i+1]], &carry))
					}

					if decoded != string(testbuf) {
						error_list += fmt.Sprintf("(util.Base64DecodeString() failed for length=%v eq=%v err=%v parts=%v)\n", length, eq, err, parts)
					}

					buffy := []byte(string(teststr))
					decbuffy := util.Base64DecodeInPlace(buffy)
					if &(decbuffy[0]) != &(buffy[0]) || // verify the in-place property
						string(decbuffy) != string(testbuf) {
						error_list += fmt.Sprintf("(util.Base64DecodeInPlace() failed for length=%v eq=%v err=%v parts=%v)\n", length, eq, err, parts)
					}
				}
			}
		}
	}

	check(error_list, "")

	buffy := make([]byte, 1024)
	st := "Nehmt, esst. Dies ist mein Leib - sprach der Schokohase"
	copy(buffy[32:], st)
	result := util.Base64EncodeInPlace(buffy[:32+len(st)], 32)
	check(&(buffy[0]) == &(result[0]), true)
	check(cap(result), cap(buffy))
	check(string(result), "TmVobXQsIGVzc3QuIERpZXMgaXN0IG1laW4gTGVpYiAtIHNwcmFjaCBkZXIgU2Nob2tvaGFzZQ==")

	st = "Nehmt, esst. Dies ist mein Leib - sprach der Schokohase\n"
	copy(buffy[256:], st)
	result = util.Base64EncodeInPlace(buffy[:256+len(st)], 256)
	check(&(buffy[0]) == &(result[0]), true)
	check(cap(result), cap(buffy))
	check(string(result), "TmVobXQsIGVzc3QuIERpZXMgaXN0IG1laW4gTGVpYiAtIHNwcmFjaCBkZXIgU2Nob2tvaGFzZQo=")

	for n := 0; n <= 12; n++ {
		buffy = make([]byte, n)
		for i := range buffy {
			buffy[i] = byte(i)
		}
		check(string(util.Base64EncodeString(string(buffy))), base64.StdEncoding.EncodeToString(buffy))
	}
}