aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKorhonen Sami (Samlink) <k847259@ubuntu.saminet.fi>2020-07-09 12:09:58 +0300
committerMatthew Heon <matthew.heon@pm.me>2020-07-22 14:46:31 -0400
commit7759c8c9f32a5443970ffc11d8db14f8d3e45494 (patch)
tree102b600821c8d33218f75f5afeeb4525ccdc53a3
parent6128cbec04fd80b62a9afe75adabd2acfd968909 (diff)
downloadpodman-7759c8c9f32a5443970ffc11d8db14f8d3e45494.tar.gz
podman-7759c8c9f32a5443970ffc11d8db14f8d3e45494.tar.bz2
podman-7759c8c9f32a5443970ffc11d8db14f8d3e45494.zip
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>
-rw-r--r--pkg/api/handlers/compat/containers_attach.go60
-rw-r--r--pkg/api/handlers/compat/exec.go14
2 files changed, 44 insertions, 30 deletions
diff --git a/pkg/api/handlers/compat/containers_attach.go b/pkg/api/handlers/compat/containers_attach.go
index 325f96b40..724b54ac4 100644
--- a/pkg/api/handlers/compat/containers_attach.go
+++ b/pkg/api/handlers/compat/containers_attach.go
@@ -1,8 +1,12 @@
package compat
import (
+ "bufio"
"fmt"
+ "io"
+ "net"
"net/http"
+ "strings"
"github.com/containers/libpod/v2/libpod"
"github.com/containers/libpod/v2/libpod/define"
@@ -12,12 +16,6 @@ import (
"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) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@@ -98,21 +96,11 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
return
}
- // Hijack the connection
- hijacker, ok := w.(http.Hijacker)
- if !ok {
- utils.InternalServerError(w, errors.Errorf("unable to hijack connection"))
- return
- }
-
- connection, buffer, err := hijacker.Hijack()
+ connection, buffer, err := AttachConnection(w, r)
if err != nil {
- utils.InternalServerError(w, errors.Wrapf(err, "error hijacking connection"))
+ utils.InternalServerError(w, err)
return
}
-
- fmt.Fprintf(connection, AttachHeader)
-
logrus.Debugf("Hijack for attach of container %s successful", ctr.ID())
// 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())
}
+
+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)
+ }
+}
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
index aee4196dd..a3b8cb573 100644
--- a/pkg/api/handlers/compat/exec.go
+++ b/pkg/api/handlers/compat/exec.go
@@ -173,21 +173,11 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
return
}
- // Hijack the connection
- hijacker, ok := w.(http.Hijacker)
- if !ok {
- utils.InternalServerError(w, errors.Errorf("unable to hijack connection"))
- return
- }
-
- connection, buffer, err := hijacker.Hijack()
+ connection, buffer, err := AttachConnection(w, r)
if err != nil {
- utils.InternalServerError(w, errors.Wrapf(err, "error hijacking connection"))
+ utils.InternalServerError(w, err)
return
}
-
- fmt.Fprintf(connection, AttachHeader)
-
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 {