mirror of
https://github.com/containers/podman.git
synced 2025-10-19 04:03:23 +08:00
Fix: Hijacking v2 endpoints to follow rfc 7230 semantics
After this patch v2 hijacking endpoints, exec/start and containers/attach follow rfc 7230 specification. Connection will only be upgraded, if client specifies upgrade headers: For tcp connections: Connection: Upgrade Upgrade: tcp For unix socket connections: Connection: Upgrade Upgrade: sock There are currently no checks if upgrade type actually matches with available protocols. Implementation just protocol that client requested Signed-off-by: Sami Korhonen <skorhone@gmail.com>
This commit is contained in:
@ -1,8 +1,12 @@
|
|||||||
package compat
|
package compat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/libpod/v2/libpod"
|
"github.com/containers/libpod/v2/libpod"
|
||||||
"github.com/containers/libpod/v2/libpod/define"
|
"github.com/containers/libpod/v2/libpod/define"
|
||||||
@ -12,12 +16,6 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttachHeader is the literal header sent for upgraded/hijacked connections for
|
|
||||||
// attach, sourced from Docker at:
|
|
||||||
// https://raw.githubusercontent.com/moby/moby/b95fad8e51bd064be4f4e58a996924f343846c85/api/server/router/container/container_routes.go
|
|
||||||
// Using literally to ensure compatibility with existing clients.
|
|
||||||
const AttachHeader = "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n"
|
|
||||||
|
|
||||||
func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||||
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
||||||
@ -98,21 +96,11 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack the connection
|
connection, buffer, err := AttachConnection(w, r)
|
||||||
hijacker, ok := w.(http.Hijacker)
|
|
||||||
if !ok {
|
|
||||||
utils.InternalServerError(w, errors.Errorf("unable to hijack connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
connection, buffer, err := hijacker.Hijack()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.InternalServerError(w, errors.Wrapf(err, "error hijacking connection"))
|
utils.InternalServerError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(connection, AttachHeader)
|
|
||||||
|
|
||||||
logrus.Debugf("Hijack for attach of container %s successful", ctr.ID())
|
logrus.Debugf("Hijack for attach of container %s successful", ctr.ID())
|
||||||
|
|
||||||
// Perform HTTP attach.
|
// Perform HTTP attach.
|
||||||
@ -126,3 +114,39 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
logrus.Debugf("Attach for container %s completed successfully", ctr.ID())
|
logrus.Debugf("Attach for container %s completed successfully", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AttachConnection(w http.ResponseWriter, r *http.Request) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
// Hijack the connection
|
||||||
|
hijacker, ok := w.(http.Hijacker)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, errors.Errorf("unable to hijack connection")
|
||||||
|
}
|
||||||
|
|
||||||
|
connection, buffer, err := hijacker.Hijack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrapf(err, "error hijacking connection")
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteAttachHeaders(r, connection)
|
||||||
|
|
||||||
|
return connection, buffer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteAttachHeaders(r *http.Request, connection io.Writer) {
|
||||||
|
// AttachHeader is the literal header sent for upgraded/hijacked connections for
|
||||||
|
// attach, sourced from Docker at:
|
||||||
|
// https://raw.githubusercontent.com/moby/moby/b95fad8e51bd064be4f4e58a996924f343846c85/api/server/router/container/container_routes.go
|
||||||
|
// Using literally to ensure compatibility with existing clients.
|
||||||
|
c := r.Header.Get("Connection")
|
||||||
|
proto := r.Header.Get("Upgrade")
|
||||||
|
if len(proto) == 0 || !strings.EqualFold(c, "Upgrade") {
|
||||||
|
// OK - can't upgrade if not requested or protocol is not specified
|
||||||
|
fmt.Fprintf(connection,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||||
|
} else {
|
||||||
|
// Upraded
|
||||||
|
fmt.Fprintf(connection,
|
||||||
|
"HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: %s\r\n\r\n",
|
||||||
|
proto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -173,21 +173,11 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack the connection
|
connection, buffer, err := AttachConnection(w, r)
|
||||||
hijacker, ok := w.(http.Hijacker)
|
|
||||||
if !ok {
|
|
||||||
utils.InternalServerError(w, errors.Errorf("unable to hijack connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
connection, buffer, err := hijacker.Hijack()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.InternalServerError(w, errors.Wrapf(err, "error hijacking connection"))
|
utils.InternalServerError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(connection, AttachHeader)
|
|
||||||
|
|
||||||
logrus.Debugf("Hijack for attach of container %s exec session %s successful", sessionCtr.ID(), sessionID)
|
logrus.Debugf("Hijack for attach of container %s exec session %s successful", sessionCtr.ID(), sessionID)
|
||||||
|
|
||||||
if err := sessionCtr.ExecHTTPStartAndAttach(sessionID, connection, buffer, nil, nil, nil); err != nil {
|
if err := sessionCtr.ExecHTTPStartAndAttach(sessionID, connection, buffer, nil, nil, nil); err != nil {
|
||||||
|
Reference in New Issue
Block a user