// Add a Tsig to an message. // Must return the mac func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) (*Msg, os.Error) { if !m.IsTsig() { panic("TSIG not last RR in additional") } rawsecret, err := packBase64([]byte(secret)) if err != nil { return nil, err } rr := m.Extra[len(m.Extra)-1].(*RR_TSIG) m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg mbuf, _ := m.Pack() buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly) if err != nil { return nil, err } t := new(RR_TSIG) h := hmac.NewMD5([]byte(rawsecret)) io.WriteString(h, string(buf)) t.MAC = hex.EncodeToString(h.Sum()) // Size is half! t.MACSize = uint16(len(t.MAC) / 2) t.Hdr = RR_Header{Name: rr.Hdr.Name, Rrtype: TypeTSIG, Class: ClassANY, Ttl: 0} t.Fudge = rr.Fudge t.TimeSigned = rr.TimeSigned t.Algorithm = rr.Algorithm t.OrigId = m.MsgHdr.Id m.Extra = append(m.Extra, t) return m, nil }
// Verify a TSIG on a message. // If the signature does not validate err contains the // error. If the it validates err is nil func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) (bool, os.Error) { rawsecret, err := packBase64([]byte(secret)) if err != nil { return false, err } // Srtip the TSIG from the incoming msg stripped, tsig, err := stripTsig(msg) if err != nil { return false, err } buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly) if err != nil { return false, err } /* if t.Name != "" { if t.Name != dns.Extra[i].Header().Name { return nil, ErrKey } } if t.Algorithm != "" { if t.Algorithm != dns.Extra[i].(*RR_TSIG).Algorithm { return nil, ErrAlg } } ti := uint64(time.Seconds()) - dns.Extra[i].(*RR_TSIG).TimeSigned if uint64(dns.Extra[i].(*RR_TSIG).Fudge) < ti { return nil, ErrTime } */ // Time needs to be checked h := hmac.NewMD5([]byte(rawsecret)) io.WriteString(h, string(buf)) return strings.ToUpper(hex.EncodeToString(h.Sum())) == strings.ToUpper(tsig.MAC), nil }
func Handler(c http.ResponseWriter, r *http.Request) { c.Header().Set("Content-Type", "application/json") api_key := r.FormValue("api_key") //base_url := r.FormValue("base_url") if api_key != Cfg.ApiKey { write(c, jsonError("failed", "Invalid api key")) return } requested_url := r.FormValue("u") if requested_url == "" { r.ParseForm() file_name := r.FormValue("file_name") if file_name == "" { write(c, jsonError("failed", "no `file_name` parameter")) return } fmt.Printf("file_name: %v\n", file_name) file, err := r.MultipartReader() if err != nil { write(c, jsonError("failed", "cannot get multipart reader")) return } part, err := file.NextPart() if err != nil { write(c, jsonError("failed", "no `u` nor `file`")) return } var data [1000]byte var i int = 0 var data_size int64 = 0 md5ed := hmac.NewMD5([]byte("cdnized-2194")) abs_path := "/tmp/" + RandStrings(100) dst_file, err := os.OpenFile(abs_path, os.O_WRONLY|os.O_CREATE, 0755) if err != nil { anlog.Error("Cannot create file `%s`. error: %s\n", abs_path, err.String()) write(c, jsonError("failed", fmt.Sprintf("cannot create temporary data. %v\n", err))) return } for data_size < r.ContentLength { i, err = part.Read(data[0:999]) if err != nil { break } _, err := md5ed.Write(data[0:i]) if err != nil { anlog.Error("Cannot calculate MD5 hash") write(c, jsonError("failed", "cannot calculate checksum")) break } _, err = dst_file.Write(data[0:i]) if err != nil { anlog.Error("Cannot write %d bytes data in file `%s`. error: %s\n", data_size, abs_path, err.String()) } data_size += int64(i) } dst_file.Close() //fmt.Printf("content-length: %v, file: %v, file-length: %v, i: %v\n", r.ContentLength, string(data[0:]), i, i) hash := fmt.Sprintf("%x", md5ed.Sum()) file_ext := path.Ext(file_name) file_name = hash + RandStrings(9) + file_ext new_path, err := os.Getwd() new_path = path.Join(new_path, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, file_name) if err != nil { anlog.Error("Cannot getwd\n") write(c, jsonError("failed", "internal error")) return } //fmt.Printf("abs_path: %v, new_path: %v\n", abs_path, new_path) if err := syscall.Rename(abs_path, new_path); err != 0 { anlog.Error("Cannot move from file `%s` to `%s`. %v.\n", abs_path, new_path, err) write(c, jsonError("failed", "internal error")) return } cdnized_url := fmt.Sprintf("http://%s/%s/%s/%s", Cfg.CdnServerName, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, file_name) anlog.Info("cdnized_url: %s\n", cdnized_url) os.Remove(abs_path) type success struct { Status string Size int64 Cdnized_url string } write(c, Jsonize(&success{"ok", data_size, cdnized_url})) return } //write(c, fmt.Sprintf("{Status: 'ok', url_path: '%s', gen: '%s'}", requested_url, x)) file_ext := path.Ext(requested_url) abs_path, _ := os.Getwd() abs_path = path.Join(abs_path, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, RandStrings(64)+file_ext) fmt.Printf("abs_path: %s\n", abs_path) var data []byte rv, lm, tsize := downloader.Download(requested_url, abs_path, true, &data) if rv != true { write(c, jsonError("failed", "Cannot fetch from source url")) return } md5ed := hmac.NewMD5([]byte("cdnized-2194")) for { brw, err := md5ed.Write(data) if err != nil { anlog.Error("Cannot calculate MD5 hash") write(c, jsonError("failed", "Internal error")) return } if brw >= tsize { break } } hash := fmt.Sprintf("%x", md5ed.Sum()) dir, _ := path.Split(abs_path) file_name := hash + RandStrings(8) + file_ext new_path := path.Join(dir, file_name) if err := syscall.Rename(abs_path, new_path); err != 0 { anlog.Error("Cannot rename from file `%s` to `%s`", abs_path, new_path) write(c, jsonError("failed", "Internal error")) return } cdnized_url := fmt.Sprintf("http://%s/%s/%s/%s", Cfg.CdnServerName, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, file_name) anlog.Info("cdnized_url: %s", cdnized_url) type success struct { Status string Lm string Size int Original string Cdnized_url string } write(c, Jsonize(&success{"ok", lm, tsize, requested_url, cdnized_url})) }