123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package webdav
- /*
- WebDAV Handler for Windows
- Yes, because Windows sucks and require a special handler
- to handle Windows request over WebDAV protocol
- */
- import (
- "fmt"
- "log"
- "net"
- "net/http"
- "path/filepath"
- "strings"
- "time"
- uuid "github.com/satori/go.uuid"
- )
- //Handle request from Windows File Explorer
- func (s *Server) HandleWindowClientAccess(w http.ResponseWriter, r *http.Request, vroot string) {
- coookieName := "arozosWebdavToken"
- cookie, err := r.Cookie(coookieName)
- if err != nil {
- //New Client! Record its uuid and IP address
- //Generate a new UUID for this client
- thisWebDAVClientID := uuid.NewV4().String()
- //Generate a new HTTP Cookie
- http.SetCookie(w, &http.Cookie{
- Name: coookieName,
- Value: thisWebDAVClientID,
- MaxAge: 3600,
- })
- ip, err := getIP(r)
- if err != nil {
- ip = "Unknown"
- }
- if ip == "::1" || ip == "127.0.0.1" {
- ip = "localhost"
- }
- log.Println("New Window WebDAV Client Connected! Assinging UUID:", thisWebDAVClientID)
- //Store this UUID with the connection
- s.windowsClientNotLoggedIn.Store(thisWebDAVClientID, &WindowClientInfo{
- Agent: r.Header["User-Agent"][0],
- LastConnectionTimestamp: time.Now().Unix(),
- UUID: thisWebDAVClientID,
- ClientIP: ip,
- })
- //OK. Serve the READONLY FS for Winwdows to remember this login
- s.serveReadOnlyWebDav(w, r)
- return
- } else {
- //This client already have a token. Extract it
- clientUUID := cookie.Value
- //Check if the client has been logged in
- value, ok := s.windowsClientLoggedIn.Load(clientUUID)
- if !ok {
- //Not logged in. Check if this is first connection
- cinfo, ok := s.windowsClientNotLoggedIn.Load(clientUUID)
- if !ok {
- //This is where the arozos data is loss about this client. Rebuild its cookie
- //Generate a new UUID for this client
- thisWebDAVClientID := uuid.NewV4().String()
- //Generate a new HTTP Cookie
- http.SetCookie(w, &http.Cookie{
- Name: coookieName,
- Value: thisWebDAVClientID,
- MaxAge: 3600,
- })
- ip, err := getIP(r)
- if err != nil {
- ip = "Unknown"
- }
- if ip == "::1" || ip == "127.0.0.1" {
- ip = "localhost"
- }
- //Store this UUID with the connection
- s.windowsClientNotLoggedIn.Store(thisWebDAVClientID, &WindowClientInfo{
- Agent: r.Header["User-Agent"][0],
- LastConnectionTimestamp: time.Now().Unix(),
- UUID: thisWebDAVClientID,
- ClientIP: ip,
- })
- //OK. Serve the READONLY FS for Winwdows to remember this login
- s.serveReadOnlyWebDav(w, r)
- } else {
- //This client is not logged in but connected before
- //log.Println("Windows client with assigned UUID: " + clientUUID + " try to access becore login validation")
- ///Rewrite the r.URL
- //Update last connection timestamp
- cinfo.(*WindowClientInfo).LastConnectionTimestamp = time.Now().Unix()
- //OK. Serve the READONLY FS for Winwdows to remember this login
- s.serveReadOnlyWebDav(w, r)
- }
- return
- } else {
- //OK. Serve this user
- clientInfo := value.(*WindowClientInfo)
- userinfo, err := s.userHandler.GetUserInfoFromUsername(clientInfo.Username)
- if err != nil {
- //User not exists?
- w.WriteHeader(http.StatusInternalServerError)
- w.Write([]byte("500 - User not exists"))
- return
- }
- fsh, err := userinfo.GetFileSystemHandlerFromVirtualPath(vroot + ":/")
- if err != nil {
- log.Println("[WebDAV] Failed to load File System Handler from request root: ", err.Error())
- http.Error(w, "Invalid ", http.StatusUnauthorized)
- return
- }
- //Get and serve the file content
- fs := s.getFsFromRealRoot(fsh, userinfo.Username, filepath.ToSlash(filepath.Join(s.prefix, vroot)))
- fs.ServeHTTP(w, r)
- }
- }
- }
- func getIP(r *http.Request) (string, error) {
- //Get IP from the X-REAL-IP header
- ip := r.Header.Get("X-REAL-IP")
- netIP := net.ParseIP(ip)
- if netIP != nil {
- return ip, nil
- }
- //Get IP from X-FORWARDED-FOR header
- ips := r.Header.Get("X-FORWARDED-FOR")
- splitIps := strings.Split(ips, ",")
- for _, ip := range splitIps {
- netIP := net.ParseIP(ip)
- if netIP != nil {
- return ip, nil
- }
- }
- //Get IP from RemoteAddr
- ip, _, err := net.SplitHostPort(r.RemoteAddr)
- if err != nil {
- return "", err
- }
- netIP = net.ParseIP(ip)
- if netIP != nil {
- return ip, nil
- }
- return "", fmt.Errorf("No valid ip found")
- }
|