summaryrefslogtreecommitdiff
path: root/internal/sshd/gssapi.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/sshd/gssapi.go')
-rw-r--r--internal/sshd/gssapi.go142
1 files changed, 142 insertions, 0 deletions
diff --git a/internal/sshd/gssapi.go b/internal/sshd/gssapi.go
new file mode 100644
index 0000000..bf65a15
--- /dev/null
+++ b/internal/sshd/gssapi.go
@@ -0,0 +1,142 @@
+package sshd
+
+import (
+ "fmt"
+
+ "github.com/openshift/gssapi"
+
+ "gitlab.com/gitlab-org/gitlab-shell/v14/internal/config"
+
+ "gitlab.com/gitlab-org/labkit/log"
+)
+
+var lib *gssapi.Lib
+
+func LoadGSSAPILib(config *config.GSSAPIConfig) error {
+ var err error
+
+ if config.Enabled {
+ options := &gssapi.Options{
+ Krb5Ktname: config.Keytab,
+ }
+
+ if config.LibPath != "" {
+ options.LibPath = config.LibPath
+ }
+
+ lib, err = gssapi.Load(options)
+
+ if err != nil {
+ log.WithError(err).Error("Unable to load GSSAPI library, gssapi-with-mic is disabled")
+ config.Enabled = false
+ }
+ }
+
+ return err
+}
+
+type OSGSSAPIServer struct {
+ Keytab string
+ ServicePrincipalName string
+
+ contextId *gssapi.CtxId
+}
+
+func (_ *OSGSSAPIServer) str2name(str string) (*gssapi.Name, error) {
+ strBuffer, err := lib.MakeBufferString(str)
+ if err != nil {
+ return nil, err
+ }
+ defer strBuffer.Release()
+
+ return strBuffer.Name(lib.GSS_C_NO_OID)
+}
+
+func (server *OSGSSAPIServer) AcceptSecContext(
+ token []byte,
+) (
+ outputToken []byte,
+ srcName string,
+ needContinue bool,
+ err error,
+) {
+ tokenBuffer, err := lib.MakeBufferBytes(token)
+ if err != nil {
+ return
+ }
+ defer tokenBuffer.Release()
+
+ var spn *gssapi.CredId = lib.GSS_C_NO_CREDENTIAL
+ if server.ServicePrincipalName != "" {
+ var name *gssapi.Name
+ name, err = server.str2name(server.ServicePrincipalName)
+ if err != nil {
+ return
+ }
+ defer name.Release()
+
+ var actualMech *gssapi.OIDSet
+ spn, actualMech, _, err = lib.AcquireCred(name, 0, lib.GSS_C_NO_OID_SET, gssapi.GSS_C_ACCEPT)
+ if err != nil {
+ return
+ }
+ defer spn.Release()
+ defer actualMech.Release()
+ }
+
+ ctxOut, srcNameName, _, outputTokenBuffer, _, _, _, err := lib.AcceptSecContext(
+ server.contextId,
+ spn,
+ tokenBuffer,
+ nil,
+ )
+ if err == gssapi.ErrContinueNeeded {
+ needContinue = true
+ err = nil
+ } else if err != nil {
+ return
+ }
+ defer outputTokenBuffer.Release()
+ defer srcNameName.Release()
+
+ outputToken = outputTokenBuffer.Bytes()
+ server.contextId = ctxOut
+
+ return outputToken, srcNameName.String(), needContinue, err
+}
+
+func (server *OSGSSAPIServer) VerifyMIC(
+ micField []byte,
+ micToken []byte,
+) error {
+ if server.contextId == nil {
+ return fmt.Errorf("gssapi: uninitialized contextId")
+ }
+
+ micFieldBuffer, err := lib.MakeBufferBytes(micField)
+ if err != nil {
+ return err
+ }
+ defer micFieldBuffer.Release()
+ micTokenBuffer, err := lib.MakeBufferBytes(micToken)
+ if err != nil {
+ return err
+ }
+ defer micTokenBuffer.Release()
+
+ _, err = server.contextId.VerifyMIC(micFieldBuffer, micTokenBuffer)
+ return err
+
+}
+
+func (server *OSGSSAPIServer) DeleteSecContext() error {
+ if server.contextId == nil {
+ return nil
+ }
+
+ err := server.contextId.DeleteSecContext()
+ if err == nil {
+ server.contextId = nil
+ }
+ return err
+}