Commit d51c7ac3 authored by Simon Wilkinson's avatar Simon Wilkinson Committed by Colin Watson

GSSAPI key exchange support

This patch has been rejected upstream: "None of the OpenSSH developers are
in favour of adding this, and this situation has not changed for several
years.  This is not a slight on Simon's patch, which is of fine quality, but
just that a) we don't trust GSSAPI implementations that much and b) we don't
like adding new KEX since they are pre-auth attack surface.  This one is
particularly scary, since it requires hooks out to typically root-owned
system resources."

However, quite a lot of people rely on this in Debian, and it's better to
have it merged into the main openssh package rather than having separate
-krb5 packages (as we used to have).  It seems to have a generally good
security history.

Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
Last-Updated: 2017-01-16

Patch-Name: gssapi.patch
parent 6fabaf6f
20110101
- Finally update for OpenSSH 5.6p1
- Add GSSAPIServerIdentity option from Jim Basney
20100308
- [ Makefile.in, key.c, key.h ]
Updates for OpenSSH 5.4p1
- [ servconf.c ]
Include GSSAPI options in the sshd -T configuration dump, and flag
some older configuration options as being unsupported. Thanks to Colin
Watson.
-
20100124
- [ sshconnect2.c ]
Adapt to deal with additional element in Authmethod structure. Thanks to
Colin Watson
20090615
- [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
sshd.c ]
Fix issues identified by Greg Hudson following a code review
Check return value of gss_indicate_mechs
Protect GSSAPI calls in monitor, so they can only be used if enabled
Check return values of bignum functions in key exchange
Use BN_clear_free to clear other side's DH value
Make ssh_gssapi_id_kex more robust
Only configure kex table pointers if GSSAPI is enabled
Don't leak mechanism list, or gss mechanism list
Cast data.length before printing
If serverkey isn't provided, use an empty string, rather than NULL
20090201
- [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
ssh_config.5 sshconnet2.c ]
Add support for the GSSAPIClientIdentity option, which allows the user
to specify which GSSAPI identity to use to contact a given server
20080404
- [ gss-serv.c ]
Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
been omitted from a previous version of this patch. Reported by Borislav
Stoichkov
20070317
- [ gss-serv-krb5.c ]
Remove C99ism, where new_ccname was being declared in the middle of a
function
20061220
- [ servconf.c ]
Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and
documented, behaviour. Reported by Dan Watson.
20060910
- [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
ssh-gss.h ]
add support for gss-group14-sha1 key exchange mechanisms
- [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
Add GSSAPIStrictAcceptorCheck option to allow the disabling of
acceptor principal checking on multi-homed machines.
<Bugzilla #928>
- [ sshd_config ssh_config ]
Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
configuration files
- [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
Limit length of error messages displayed by client
20060909
- [ gss-genr.c gss-serv.c ]
move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
only, where they belong
<Bugzilla #1225>
20060829
- [ gss-serv-krb5.c ]
Fix CCAPI credentials cache name when creating KRB5CCNAME environment
variable
20060828
- [ gss-genr.c ]
Avoid Heimdal context freeing problem
<Fixed upstream 20060829>
20060818
- [ gss-genr.c ssh-gss.h sshconnect2.c ]
Make sure that SPENGO is disabled
<Bugzilla #1218 - Fixed upstream 20060818>
20060421
- [ gssgenr.c, sshconnect2.c ]
a few type changes (signed versus unsigned, int versus size_t) to
fix compiler errors/warnings
(from jbasney AT ncsa.uiuc.edu)
- [ kexgssc.c, sshconnect2.c ]
fix uninitialized variable warnings
(from jbasney AT ncsa.uiuc.edu)
- [ gssgenr.c ]
pass oid to gss_display_status (helpful when using GSSAPI mechglue)
(from jbasney AT ncsa.uiuc.edu)
<Bugzilla #1220 >
- [ gss-serv-krb5.c ]
#ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
(from jbasney AT ncsa.uiuc.edu)
<Fixed upstream 20060304>
- [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c
add client-side GssapiKeyExchange option
(from jbasney AT ncsa.uiuc.edu)
- [ sshconnect2.c ]
add support for GssapiTrustDns option for gssapi-with-mic
(from jbasney AT ncsa.uiuc.edu)
<gssapi-with-mic support is Bugzilla #1008>
......@@ -92,6 +92,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
kexgssc.o \
platform-pledge.o platform-tracing.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
......@@ -105,7 +106,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor.o monitor_wrap.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
......
......@@ -182,8 +182,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
len = strlen(authctxt->krb5_ticket_file) + 6;
authctxt->krb5_ccname = xmalloc(len);
#ifdef USE_CCAPI
snprintf(authctxt->krb5_ccname, len, "API:%s",
authctxt->krb5_ticket_file);
#else
snprintf(authctxt->krb5_ccname, len, "FILE:%s",
authctxt->krb5_ticket_file);
#endif
#ifdef USE_PAM
if (options.use_pam)
......@@ -240,15 +245,22 @@ krb5_cleanup_proc(Authctxt *authctxt)
#ifndef HEIMDAL
krb5_error_code
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
int tmpfd, ret, oerrno;
int ret, oerrno;
char ccname[40];
mode_t old_umask;
#ifdef USE_CCAPI
char cctemplate[] = "API:krb5cc_%d";
#else
char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
int tmpfd;
#endif
ret = snprintf(ccname, sizeof(ccname),
"FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
cctemplate, geteuid());
if (ret < 0 || (size_t)ret >= sizeof(ccname))
return ENOMEM;
#ifndef USE_CCAPI
old_umask = umask(0177);
tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
......@@ -265,6 +277,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
return oerrno;
}
close(tmpfd);
#endif
return (krb5_cc_resolve(ctx, ccname, ccache));
}
......
......@@ -372,7 +372,8 @@ auth_root_allowed(const char *method)
case PERMIT_NO_PASSWD:
if (strcmp(method, "publickey") == 0 ||
strcmp(method, "hostbased") == 0 ||
strcmp(method, "gssapi-with-mic") == 0)
strcmp(method, "gssapi-with-mic") == 0 ||
strcmp(method, "gssapi-keyex") == 0)
return 1;
break;
case PERMIT_FORCED_ONLY:
......@@ -794,99 +795,6 @@ fakepw(void)
return (&fake);
}
/*
* Returns the remote DNS hostname as a string. The returned string must not
* be freed. NB. this will usually trigger a DNS query the first time it is
* called.
* This function does additional checks on the hostname to mitigate some
* attacks on legacy rhosts-style authentication.
* XXX is RhostsRSAAuthentication vulnerable to these?
* XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
*/
static char *
remote_hostname(struct ssh *ssh)
{
struct sockaddr_storage from;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[NI_MAXHOST], ntop2[NI_MAXHOST];
const char *ntop = ssh_remote_ipaddr(ssh);
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
return strdup(ntop);
}
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) != 0) {
/* Host name not found. Use ip address. */
return strdup(ntop);
}
/*
* if reverse lookup result looks like a numeric hostname,
* someone is trying to trick us by PTR record like following:
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
*/
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
name, ntop);
freeaddrinfo(ai);
return strdup(ntop);
}
/* Names are stored in lowercase. */
lowercase(name);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
logit("reverse mapping checking getaddrinfo for %.700s "
"[%s] failed.", name, ntop);
return strdup(ntop);
}
/* Look for the address from the list of addresses. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
(strcmp(ntop, ntop2) == 0))
break;
}
freeaddrinfo(aitop);
/* If we reached the end of the list, the address was not there. */
if (ai == NULL) {
/* Address not found for the host name. */
logit("Address %.100s maps to %.600s, but this does not "
"map back to the address.", ntop, name);
return strdup(ntop);
}
return strdup(name);
}
/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
......
/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
* Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -53,6 +53,40 @@ static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_errtok(int, u_int32_t, void *);
/*
* The 'gssapi_keyex' userauth mechanism.
*/
static int
userauth_gsskeyex(Authctxt *authctxt)
{
int authenticated = 0;
Buffer b;
gss_buffer_desc mic, gssbuf;
u_int len;
mic.value = packet_get_string(&len);
mic.length = len;
packet_check_eom();
ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
"gssapi-keyex");
gssbuf.value = buffer_ptr(&b);
gssbuf.length = buffer_len(&b);
/* gss_kex_context is NULL with privsep, so we can't check it here */
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
&gssbuf, &mic))))
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
authctxt->pw));
buffer_free(&b);
free(mic.value);
return (authenticated);
}
/*
* We only support those mechanisms that we know about (ie ones that we know
* how to check local user kuserok and the like)
......@@ -238,7 +272,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
packet_check_eom();
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
authctxt->pw));
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
......@@ -274,7 +309,8 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
gssbuf.length = buffer_len(&b);
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
authenticated =
PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
else
logit("GSSAPI MIC check failed");
......@@ -290,6 +326,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
return 0;
}
Authmethod method_gsskeyex = {
"gssapi-keyex",
userauth_gsskeyex,
&options.gss_authentication
};
Authmethod method_gssapi = {
"gssapi-with-mic",
userauth_gssapi,
......
......@@ -70,6 +70,7 @@ extern Authmethod method_passwd;
extern Authmethod method_kbdint;
extern Authmethod method_hostbased;
#ifdef GSSAPI
extern Authmethod method_gsskeyex;
extern Authmethod method_gssapi;
#endif
......@@ -77,6 +78,7 @@ Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
#ifdef GSSAPI
&method_gsskeyex,
&method_gssapi,
#endif
&method_passwd,
......
......@@ -35,6 +35,99 @@
#include "canohost.h"
#include "misc.h"
/*
* Returns the remote DNS hostname as a string. The returned string must not
* be freed. NB. this will usually trigger a DNS query the first time it is
* called.
* This function does additional checks on the hostname to mitigate some
* attacks on legacy rhosts-style authentication.
* XXX is RhostsRSAAuthentication vulnerable to these?
* XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
*/
char *
remote_hostname(struct ssh *ssh)
{
struct sockaddr_storage from;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[NI_MAXHOST], ntop2[NI_MAXHOST];
const char *ntop = ssh_remote_ipaddr(ssh);
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
return strdup(ntop);
}
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) != 0) {
/* Host name not found. Use ip address. */
return strdup(ntop);
}
/*
* if reverse lookup result looks like a numeric hostname,
* someone is trying to trick us by PTR record like following:
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
*/
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
name, ntop);
freeaddrinfo(ai);
return strdup(ntop);
}
/* Names are stored in lowercase. */
lowercase(name);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
logit("reverse mapping checking getaddrinfo for %.700s "
"[%s] failed.", name, ntop);
return strdup(ntop);
}
/* Look for the address from the list of addresses. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
(strcmp(ntop, ntop2) == 0))
break;
}
freeaddrinfo(aitop);
/* If we reached the end of the list, the address was not there. */
if (ai == NULL) {
/* Address not found for the host name. */
logit("Address %.100s maps to %.600s, but this does not "
"map back to the address.", ntop, name);
return strdup(ntop);
}
return strdup(name);
}
void
ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
{
......
......@@ -15,6 +15,9 @@
#ifndef _CANOHOST_H
#define _CANOHOST_H
struct ssh;
char *remote_hostname(struct ssh *);
char *get_peer_ipaddr(int);
int get_peer_port(int);
char *get_local_ipaddr(int);
......
......@@ -113,6 +113,10 @@
#include "ssherr.h"
#include "hostfile.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
/* import options */
extern Options options;
......@@ -1664,9 +1668,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
break;
/* Do channel operations unless rekeying in progress. */
if (!ssh_packet_is_rekeying(active_state))
if (!ssh_packet_is_rekeying(active_state)) {
channel_after_select(readset, writeset);
#ifdef GSSAPI
if (options.gss_renewal_rekey &&
ssh_gssapi_credentials_updated(NULL)) {
debug("credentials updated - forcing rekey");
need_rekeying = 1;
}
#endif
}
/* Buffer input from the connection. */
client_process_net_input(readset);
......
......@@ -1670,6 +1670,9 @@
/* Use btmp to log bad logins */
#undef USE_BTMP
/* platform uses an in-memory credentials cache */
#undef USE_CCAPI
/* Use libedit for sftp */
#undef USE_LIBEDIT
......@@ -1685,6 +1688,9 @@
/* Use PIPES instead of a socketpair() */
#undef USE_PIPES
/* platform has the Security Authorization Session API */
#undef USE_SECURITY_SESSION_API
/* Define if you have Solaris privileges */
#undef USE_SOLARIS_PRIVS
......
......@@ -623,6 +623,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
[Use tunnel device compatibility to OpenBSD])
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
AC_MSG_CHECKING([if we have the Security Authorization Session API])
AC_TRY_COMPILE([#include <Security/AuthSession.h>],
[SessionCreate(0, 0);],
[ac_cv_use_security_session_api="yes"
AC_DEFINE([USE_SECURITY_SESSION_API], [1],
[platform has the Security Authorization Session API])
LIBS="$LIBS -framework Security"
AC_MSG_RESULT([yes])],
[ac_cv_use_security_session_api="no"
AC_MSG_RESULT([no])])
AC_MSG_CHECKING([if we have an in-memory credentials cache])
AC_TRY_COMPILE(
[#include <Kerberos/Kerberos.h>],
[cc_context_t c;
(void) cc_initialize (&c, 0, NULL, NULL);],
[AC_DEFINE([USE_CCAPI], [1],
[platform uses an in-memory credentials cache])
LIBS="$LIBS -framework Security"
AC_MSG_RESULT([yes])
if test "x$ac_cv_use_security_session_api" = "xno"; then
AC_MSG_ERROR([*** Need a security framework to use the credentials cache API ***])
fi],
[AC_MSG_RESULT([no])]
)
m4_pattern_allow([AU_IPv])
AC_CHECK_DECL([AU_IPv4], [],
AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
......
/* $OpenBSD: gss-genr.c,v 1.24 2016/09/12 01:22:38 deraadt Exp $ */
/*
* Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
* Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -40,12 +40,167 @@
#include "buffer.h"
#include "log.h"
#include "ssh2.h"
#include "cipher.h"
#include "key.h"
#include "kex.h"
#include <openssl/evp.h>
#include "ssh-gss.h"
extern u_char *session_id2;
extern u_int session_id2_len;
typedef struct {
char *encoded;
gss_OID oid;
} ssh_gss_kex_mapping;
/*
* XXX - It would be nice to find a more elegant way of handling the
* XXX passing of the key exchange context to the userauth routines
*/
Gssctxt *gss_kex_context = NULL;
static ssh_gss_kex_mapping *gss_enc2oid = NULL;
int
ssh_gssapi_oid_table_ok(void) {
return (gss_enc2oid != NULL);
}
/*
* Return a list of the gss-group1-sha1 mechanisms supported by this program
*
* We test mechanisms to ensure that we can use them, to avoid starting
* a key exchange with a bad mechanism
*/
char *
ssh_gssapi_client_mechanisms(const char *host, const char *client) {
gss_OID_set gss_supported;
OM_uint32 min_status;
if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
return NULL;
return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
host, client));
}
char *
ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
const char *host, const char *client) {
Buffer buf;
size_t i;
int oidpos, enclen;
char *mechs, *encoded;
u_char digest[EVP_MAX_MD_SIZE];
char deroid[2];
const EVP_MD *evp_md = EVP_md5();
EVP_MD_CTX md;
if (gss_enc2oid != NULL) {
for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
free(gss_enc2oid[i].encoded);
free(gss_enc2oid);
}
gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
(gss_supported->count + 1));
buffer_init(&buf);
oidpos = 0;
for (i = 0; i < gss_supported->count; i++) {
if (gss_supported->elements[i].length < 128 &&
(*check)(NULL, &(gss_supported->elements[i]), host, client)) {
deroid[0] = SSH_GSS_OIDTYPE;
deroid[1] = gss_supported->elements[i].length;
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, deroid, 2);
EVP_DigestUpdate(&md,
gss_supported->elements[i].elements,
gss_supported->elements[i].length);
EVP_DigestFinal(&md, digest, NULL);
encoded = xmalloc(EVP_MD_size(evp_md) * 2);
enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
encoded, EVP_MD_size(evp_md) * 2);
if (oidpos != 0)
buffer_put_char(&buf, ',');
buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
buffer_append(&buf, encoded, enclen);
buffer_put_char(&buf, ',');
buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID,
sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
buffer_append(&buf, encoded, enclen);
buffer_put_char(&buf, ',');
buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
buffer_append(&buf, encoded, enclen);
gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
gss_enc2oid[oidpos].encoded = encoded;
oidpos++;
}
}
gss_enc2oid[oidpos].oid = NULL;
gss_enc2oid[oidpos].encoded = NULL;
buffer_put_char(&buf, '\0');
mechs = xmalloc(buffer_len(&buf));
buffer_get(&buf, mechs, buffer_len(&buf));
buffer_free(&buf);
if (strlen(mechs) == 0) {
free(mechs);
mechs = NULL;
}
return (mechs);
}
gss_OID
ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
int i = 0;
switch (kex_type) {
case KEX_GSS_GRP1_SHA1:
if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
return GSS_C_NO_OID;
name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
break;
case KEX_GSS_GRP14_SHA1:
if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
return GSS_C_NO_OID;
name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
break;
case KEX_GSS_GEX_SHA1:
if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
return GSS_C_NO_OID;
name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
break;
default:
return GSS_C_NO_OID;
}
while (gss_enc2oid[i].encoded != NULL &&
strcmp(name, gss_enc2oid[i].encoded) != 0)
i++;
if (gss_enc2oid[i].oid != NULL && ctx != NULL)
ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
return gss_enc2oid[i].oid;
}
/* Check that the OID in a data stream matches that in the context */
int
ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
...