package main import ( "fmt" "io" "log" "net/http" "os" "path" "github.com/cavaliergopher/cpio" ) func passwd(w http.ResponseWriter, r *http.Request) { if addr := r.Header.Get("X-Forwarded-For"); addr != "" { r.RemoteAddr = addr } log.Printf("%s \"%s %s\" [%s]\n", r.RemoteAddr, r.Method, r.URL.Path, r.UserAgent()) w.Header().Set("Content-Type", "text/plain") // Check request type and size if r.Method != "POST" { http.Error(w, "Invalid request", http.StatusBadRequest) return } else if r.ContentLength < 0 || r.ContentLength > 655360 { http.Error(w, "Request entity too large", http.StatusRequestEntityTooLarge) return } // Authenticate the request // Retrieve the file file, header, err := r.FormFile("shadow") if err != nil { log.Println("Error when retrieving shadow file from", r.RemoteAddr, err.Error()) http.Error(w, "Unable to read your passwd file: something is wrong in your request", http.StatusBadRequest) return } defer file.Close() // Save the file fd, err := os.Create(path.Join(tftpDir, "shadows", fmt.Sprintf("%s.cpio", r.RemoteAddr))) if err != nil { log.Println("Error when creating shadow file from", r.RemoteAddr, err.Error()) http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError) return } defer fd.Close() // Generate the new cpio archive wcpio := cpio.NewWriter(fd) hdr := &cpio.Header{ Name: "etc/shadow", Mode: 0640, Size: header.Size, } if err := wcpio.WriteHeader(hdr); err != nil { log.Println("Error when writing cpio header from", r.RemoteAddr, err.Error()) http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError) return } body, err := io.ReadAll(file) if err != nil { log.Println("Error when writing cpio body from", r.RemoteAddr, err.Error()) http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError) return } if _, err := wcpio.Write(body); err != nil { log.Println("Error when writing cpio file from", r.RemoteAddr, err.Error()) http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError) return } if err := wcpio.Close(); err != nil { log.Println("Error when closing cpio file from", r.RemoteAddr, err.Error()) http.Error(w, "Unable to treat your passwd file, please try again later", http.StatusInternalServerError) return } log.Println("Registered shadow from", r.RemoteAddr) http.Error(w, "Success", http.StatusOK) }