// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ssh import ( "encoding/asn1" "errors" ) var krb5OID []byte func init() { krb5OID, _ = asn1.Marshal(krb5Mesh) } // GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins. type GSSAPIClient interface { // InitSecContext initiates the establishment of a security context for GSS-API between the // ssh client and ssh server. Initially the token parameter should be specified as nil. // The routine may return a outputToken which should be transferred to // the ssh server, where the ssh server will present it to // AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting // needContinue to false. To complete the context // establishment, one or more reply tokens may be required from the ssh // server;if so, InitSecContext will return a needContinue which is true. // In this case, InitSecContext should be called again when the // reply token is received from the ssh server, passing the reply // token to InitSecContext via the token parameters. // See RFC 2743 section 2.2.1 and RFC 4462 section 3.4. InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) // GetMIC generates a cryptographic MIC for the SSH2 message, and places // the MIC in a token for transfer to the ssh server. // The contents of the MIC field are obtained by calling GSS_GetMIC() // over the following, using the GSS-API context that was just // established: // string session identifier // byte SSH_MSG_USERAUTH_REQUEST // string user name // string service // string "gssapi-with-mic" // See RFC 2743 section 2.3.1 and RFC 4462 3.5. GetMIC(micFiled []byte) ([]byte, error) // Whenever possible, it should be possible for // DeleteSecContext() calls to be successfully processed even // if other calls cannot succeed, thereby enabling context-related // resources to be released. // In addition to deleting established security contexts, // gss_delete_sec_context must also be able to delete "half-built" // security contexts resulting from an incomplete sequence of // InitSecContext()/AcceptSecContext() calls. // See RFC 2743 section 2.2.3. DeleteSecContext() error } // GSSAPIServer provides the API to plug in GSSAPI authentication for server logins. type GSSAPIServer interface { // AcceptSecContext allows a remotely initiated security context between the application // and a remote peer to be established by the ssh client. The routine may return a // outputToken which should be transferred to the ssh client, // where the ssh client will present it to InitSecContext. // If no token need be sent, AcceptSecContext will indicate this // by setting the needContinue to false. To // complete the context establishment, one or more reply tokens may be // required from the ssh client. if so, AcceptSecContext // will return a needContinue which is true, in which case it // should be called again when the reply token is received from the ssh // client, passing the token to AcceptSecContext via the // token parameters. // The srcName return value is the authenticated username. // See RFC 2743 section 2.2.2 and RFC 4462 section 3.4. AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) // VerifyMIC verifies that a cryptographic MIC, contained in the token parameter, // fits the supplied message is received from the ssh client. // See RFC 2743 section 2.3.2. VerifyMIC(micField []byte, micToken []byte) error // Whenever possible, it should be possible for // DeleteSecContext() calls to be successfully processed even // if other calls cannot succeed, thereby enabling context-related // resources to be released. // In addition to deleting established security contexts, // gss_delete_sec_context must also be able to delete "half-built" // security contexts resulting from an incomplete sequence of // InitSecContext()/AcceptSecContext() calls. // See RFC 2743 section 2.2.3. DeleteSecContext() error } var ( // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication, // so we also support the krb5 mechanism only. // See RFC 1964 section 1. krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2} ) // The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST // See RFC 4462 section 3.2. type userAuthRequestGSSAPI struct { N uint32 OIDS []asn1.ObjectIdentifier } func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) { n, rest, ok := parseUint32(payload) if !ok { return nil, errors.New("parse uint32 failed") } s := &userAuthRequestGSSAPI{ N: n, OIDS: make([]asn1.ObjectIdentifier, n), } for i := 0; i < int(n); i++ { var ( desiredMech []byte err error ) desiredMech, rest, ok = parseString(rest) if !ok { return nil, errors.New("parse string failed") } if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil { return nil, err } } return s, nil } // See RFC 4462 section 3.6. func buildMIC(sessionID string, username string, service string, authMethod string) []byte { out := make([]byte, 0, 0) out = appendString(out, sessionID) out = append(out, msgUserAuthRequest) out = appendString(out, username) out = appendString(out, service) out = appendString(out, authMethod) return out }