Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Generic GSS-API Mechanisms #1

Open
wants to merge 3 commits into
base: draft
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -4026,7 +4026,7 @@ AC_ARG_WITH([kerberos5],
blibpath="$blibpath:${KRB5ROOT}/lib"
fi

AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h gssapi/gssapi_ext.h])
AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h])
AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h])

Expand All @@ -4047,8 +4047,10 @@ AC_ARG_WITH([kerberos5],
#endif
]])
saved_LIBS="$LIBS"
LIBS="$LIBS $K5LIBS"
LIBS="$LIBS $K5LIBS $GSSLIBS"
AC_CHECK_FUNCS([krb5_cc_new_unique krb5_get_error_message krb5_free_error_message])
AC_CHECK_FUNCS([gss_localname gss_userok])
AC_CHECK_FUNCS([gss_indicate_mechs_by_attrs])
LIBS="$saved_LIBS"

fi
Expand Down
114 changes: 98 additions & 16 deletions gss-serv.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,67 @@
extern ServerOptions options;

static ssh_gssapi_client gssapi_client =
{ GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL}, 0, 0};
{ {0, NULL}, GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0};

ssh_gssapi_mech gssapi_null_mech =
{ NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};

/* Generic GSS-API support*/
#ifdef HAVE_GSS_USEROK
static int ssh_gssapi_generic_userok(
ssh_gssapi_client *client, char *user) {
if (gss_userok(client->ctx_name, user)) {
debug("userok succeded for %s", user);
return 1;
} else {
debug("userok failed for %s", user);
return 0;
}
}
#endif

#ifdef HAVE_GSS_USEROK
static int
ssh_gssapi_generic_localname(ssh_gssapi_client *client,
char **localname) {
#ifdef HAVE_GSS_LOCALNAME
gss_buffer_desc lbuffer;
OM_uint32 major, minor;
*localname = NULL;
major = gss_localname(&minor, client->cred_name, NULL, &lbuffer);
if (GSS_ERROR(major))
return 0;
if (lbuffer.value == NULL)
return 0;
*localname = xmalloc(lbuffer.length+1);
if (*localname) {
memcpy(*localname, lbuffer.value, lbuffer.length);
*localname[lbuffer.length] = '\0';
}
gss_release_buffer(&minor, &lbuffer);
if (*localname)
return 1;
return 0;
#else
debug("No generic gss_localname");
return 0;
#endif
}

static ssh_gssapi_mech ssh_gssapi_generic_mech = {
NULL, NULL,
{0, NULL},
NULL, /* dochild */
ssh_gssapi_generic_userok,
ssh_gssapi_generic_localname,
NULL,
NULL};
static const ssh_gssapi_mech *ssh_gssapi_generic_mech_ptr = &ssh_gssapi_generic_mech;
#else /*HAVE_GSS_USEROK*/
static const ssh_gssapi_mech *ssh_gssapi_generic_mech_ptr = NULL;
#endif

#ifdef KRB5
extern ssh_gssapi_mech gssapi_kerberos_mech;
#endif
Expand Down Expand Up @@ -176,6 +231,27 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset)
int present;
gss_OID_set supported;

#ifdef HAVE_GSS_INDICATE_MECHS_BY_ATTRS
/* If we have a generic mechanism all OIDs supported */
if (ssh_gssapi_generic_mech_ptr) {
gss_OID_desc except_oids[3];
gss_OID_set_desc except_attrs;
except_oids[0] = *GSS_C_MA_MECH_NEGO;
except_oids[1] = *GSS_C_MA_NOT_MECH;
except_oids[2] = *GSS_C_MA_DEPRECATED;

except_attrs.count = sizeof(except_oids)/sizeof(except_oids[0]);
except_attrs.elements = except_oids;

if (!GSS_ERROR(gss_indicate_mechs_by_attrs(&min_status,
GSS_C_NO_OID_SET,
&except_attrs,
GSS_C_NO_OID_SET,
oidset)))
return;
}
#endif

gss_create_empty_oid_set(&min_status, oidset);

if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
Expand Down Expand Up @@ -310,8 +386,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;

if (options.gss_store_rekey && client->used && ctx->client_creds) {
if (client->mech->oid.length != ctx->oid->length ||
(memcmp(client->mech->oid.elements,
if (client->oid.length != ctx->oid->length ||
(memcmp(client->oid.elements,
ctx->oid->elements, ctx->oid->length) !=0)) {
debug("Rekeyed credentials have different mechanism");
return GSS_S_COMPLETE;
Expand All @@ -324,7 +400,7 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
return (ctx->major);
}

ctx->major = gss_compare_name(&ctx->minor, client->name,
ctx->major = gss_compare_name(&ctx->minor, client->cred_name,
new_name, &equal);

if (GSS_ERROR(ctx->major)) {
Expand All @@ -339,9 +415,9 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)

debug("Marking rekeyed credentials for export");

gss_release_name(&ctx->minor, &client->name);
gss_release_name(&ctx->minor, &client->cred_name);
gss_release_cred(&ctx->minor, &client->creds);
client->name = new_name;
client->cred_name = new_name;
client->creds = ctx->client_creds;
ctx->client_creds = GSS_C_NO_CREDENTIAL;
client->updated = 1;
Expand All @@ -358,12 +434,17 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
i++;
}

if (client->mech == NULL)
return GSS_S_FAILURE;
if (client->oid.elements == NULL)
client->oid = *ctx->oid;
if (client->mech == NULL) {
if (ssh_gssapi_generic_mech_ptr)
client->mech = (ssh_gssapi_mech *) ssh_gssapi_generic_mech_ptr;
else return GSS_S_FAILURE;
}

if (ctx->client_creds &&
(ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
ctx->client_creds, ctx->oid, &client->cred_name, NULL, NULL, NULL))) {
ssh_gssapi_error(ctx);
return (ctx->major);
}
Expand All @@ -380,11 +461,16 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
return (ctx->major);
}

if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
if ((client->mech->oid.elements != NULL) &&
(ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
&client->exportedname))) {
return (ctx->major);
}

if ((ctx->major = gss_duplicate_name(&ctx->minor, ctx->client,
&client->ctx_name)))
return ctx->major;

gss_release_buffer(&ctx->minor, &ename);

/* We can't copy this structure, so we just move the pointer to it */
Expand Down Expand Up @@ -438,11 +524,6 @@ ssh_gssapi_userok(char *user, struct passwd *pw)
{
OM_uint32 lmin;

if (gssapi_client.exportedname.length == 0 ||
gssapi_client.exportedname.value == NULL) {
debug("No suitable client data");
return 0;
}
if (gssapi_client.mech && gssapi_client.mech->userok)
if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
gssapi_client.used = 1;
Expand All @@ -453,6 +534,7 @@ ssh_gssapi_userok(char *user, struct passwd *pw)
gss_release_buffer(&lmin, &gssapi_client.displayname);
gss_release_buffer(&lmin, &gssapi_client.exportedname);
gss_release_cred(&lmin, &gssapi_client.creds);
gss_release_name(&lmin, &gssapi_client.ctx_name);
explicit_bzero(&gssapi_client,
sizeof(ssh_gssapi_client));
return 0;
Expand Down
8 changes: 6 additions & 2 deletions ssh-gss.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
#elif defined(HAVE_GSSAPI_GSSAPI_H)
#include <gssapi/gssapi.h>
#endif
#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
#include <gssapi/gssapi_ext.h>
#endif

#ifdef KRB5
# ifndef HEIMDAL
Expand Down Expand Up @@ -81,10 +84,11 @@ typedef struct {
} ssh_gssapi_ccache;

typedef struct {
gss_OID_desc oid;
gss_buffer_desc displayname;
gss_buffer_desc exportedname;
gss_cred_id_t creds;
gss_name_t name;
gss_name_t cred_name, ctx_name;
struct ssh_gssapi_mech_struct *mech;
ssh_gssapi_ccache store;
int used;
Expand All @@ -107,7 +111,7 @@ typedef struct {
OM_uint32 minor; /* both */
gss_ctx_id_t context; /* both */
gss_name_t name; /* both */
gss_OID oid; /* client */
gss_OID oid; /* both */
gss_cred_id_t creds; /* server */
gss_name_t client; /* server */
gss_cred_id_t client_creds; /* both */
Expand Down