X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/f472818dbd4776623983e221752ec18aa17afe85..16ff2507b47a9820fc2a82566a9dd46dad2e2409:/openssh/gss-genr.c diff --git a/openssh/gss-genr.c b/openssh/gss-genr.c index 9bc2a84..92cd09a 100644 --- a/openssh/gss-genr.c +++ b/openssh/gss-genr.c @@ -1,7 +1,7 @@ -/* $OpenBSD: gss-genr.c,v 1.6 2005/10/13 22:24:31 stevesk Exp $ */ +/* $OpenBSD: gss-genr.c,v 1.19 2007/06/12 11:56:15 dtucker Exp $ */ /* - * Copyright (c) 2001-2005 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 @@ -28,11 +28,21 @@ #ifdef GSSAPI +#include +#include + +#include +#include +#include + #include "xmalloc.h" -#include "bufaux.h" +#include "buffer.h" #include "log.h" #include "canohost.h" #include "ssh2.h" +#include "cipher.h" +#include "key.h" +#include "kex.h" #include #include "ssh-gss.h" @@ -66,7 +76,6 @@ ssh_gssapi_oid_table_ok() { * a key exchange with a bad mechanism */ - char * ssh_gssapi_client_mechanisms(const char *host) { gss_OID_set gss_supported; @@ -75,12 +84,12 @@ ssh_gssapi_client_mechanisms(const char *host) { gss_indicate_mechs(&min_status, &gss_supported); return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, - (void *)host)); + host)); } char * ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, - void *data) { + const char *data) { Buffer buf; size_t i; int oidpos, enclen; @@ -91,20 +100,20 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, EVP_MD_CTX md; if (gss_enc2oid != NULL) { - for (i=0;gss_enc2oid[i].encoded!=NULL;i++) + for (i = 0; gss_enc2oid[i].encoded != NULL; i++) xfree(gss_enc2oid[i].encoded); xfree(gss_enc2oid); } - gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping)* - (gss_supported->count+1)); + 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++) { + for (i = 0; i < gss_supported->count; i++) { if (gss_supported->elements[i].length < 128 && - (*check)(&(gss_supported->elements[i]), data)) { + (*check)(NULL, &(gss_supported->elements[i]), data)) { deroid[0] = SSH_GSS_OIDTYPE; deroid[1] = gss_supported->elements[i].length; @@ -116,19 +125,23 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, gss_supported->elements[i].length); EVP_DigestFinal(&md, digest, NULL); - encoded = xmalloc(EVP_MD_size(evp_md)*2); + encoded = xmalloc(EVP_MD_size(evp_md) * 2); enclen = __b64_ntop(digest, EVP_MD_size(evp_md), - encoded, EVP_MD_size(evp_md)*2); + encoded, EVP_MD_size(evp_md) * 2); if (oidpos != 0) - buffer_put_char(&buf, ','); + buffer_put_char(&buf, ','); buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, - sizeof(KEX_GSS_GEX_SHA1_ID)-1); + sizeof(KEX_GSS_GEX_SHA1_ID) - 1); buffer_append(&buf, encoded, enclen); - buffer_put_char(&buf,','); + buffer_put_char(&buf, ','); buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, - sizeof(KEX_GSS_GRP1_SHA1_ID)-1); + 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]); @@ -154,25 +167,26 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, } gss_OID -ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int *gex) { +ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { int i = 0; - - if (strncmp(name, KEX_GSS_GRP1_SHA1_ID, - sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) { - name+=sizeof(KEX_GSS_GRP1_SHA1_ID)-1; - *gex = 0; - } else if (strncmp(name, KEX_GSS_GEX_SHA1_ID, - sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) { - name+=sizeof(KEX_GSS_GEX_SHA1_ID)-1; - *gex = 1; - } else { - return NULL; + + switch (kex_type) { + case KEX_GSS_GRP1_SHA1: + name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; + break; + case KEX_GSS_GRP14_SHA1: + name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; + break; + case KEX_GSS_GEX_SHA1: + 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) { + 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); @@ -214,7 +228,11 @@ ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid) void ssh_gssapi_error(Gssctxt *ctxt) { - debug("%s", ssh_gssapi_last_error(ctxt, NULL, NULL)); + char *s; + + s = ssh_gssapi_last_error(ctxt, NULL, NULL); + debug("%s", s); + xfree(s); } char * @@ -273,9 +291,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, void ssh_gssapi_build_ctx(Gssctxt **ctx) { - *ctx = xmalloc(sizeof (Gssctxt)); - (*ctx)->major = 0; - (*ctx)->minor = 0; + *ctx = xcalloc(1, sizeof (Gssctxt)); (*ctx)->context = GSS_C_NO_CONTEXT; (*ctx)->name = GSS_C_NO_NAME; (*ctx)->oid = GSS_C_NO_OID; @@ -350,6 +366,7 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) { gss_buffer_desc gssbuf; char *xhost; + char *val; /* Make a copy of the host name, in case it was returned by a * previous call to gethostbyname(). */ @@ -359,9 +376,9 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) * this for us themselves */ resolve_localhost(&xhost); - gssbuf.length = sizeof("host@") + strlen(xhost); - gssbuf.value = xmalloc(gssbuf.length); - snprintf(gssbuf.value, gssbuf.length, "host@%s", xhost); + xasprintf(&val, "host@%s", xhost); + gssbuf.value = val; + gssbuf.length = strlen(gssbuf.value); if ((ctx->major = gss_import_name(&ctx->minor, &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) @@ -372,41 +389,9 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) return (ctx->major); } -/* Acquire credentials for a server running on the current host. - * Requires that the context structure contains a valid OID - */ - -/* Returns a GSSAPI error code */ -OM_uint32 -ssh_gssapi_acquire_cred(Gssctxt *ctx) -{ - OM_uint32 status; - char lname[MAXHOSTNAMELEN]; - gss_OID_set oidset; - - gss_create_empty_oid_set(&status, &oidset); - gss_add_oid_set_member(&status, ctx->oid, &oidset); - - if (gethostname(lname, MAXHOSTNAMELEN)) - return (-1); - - if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) - return (ctx->major); - - if ((ctx->major = gss_acquire_cred(&ctx->minor, - ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) - ssh_gssapi_error(ctx); - - gss_release_oid_set(&status, &oidset); - return (ctx->major); -} - OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { - if (ctx == NULL) - return -1; - if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); @@ -415,16 +400,17 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) } /* Priviledged when used by server */ +/* Moved here from gss-serv.c because called by kexgss_client(). */ OM_uint32 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) { - if (ctx == NULL) - return -1; + if (ctx == NULL) + return -1; - ctx->major = gss_verify_mic(&ctx->minor, ctx->context, - gssbuf, gssmic, NULL); + ctx->major = gss_verify_mic(&ctx->minor, ctx->context, + gssbuf, gssmic, NULL); - return (ctx->major); + return (ctx->major); } void @@ -439,28 +425,37 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, buffer_put_cstring(b, context); } -OM_uint32 -ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) +int +ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) { - if (*ctx) - ssh_gssapi_delete_ctx(ctx); + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; + Gssctxt *intctx = NULL; + + if (ctx == NULL) + ctx = &intctx; + + /* RFC 4462 says we MUST NOT do SPNEGO */ + if (oid->length == spnego_oid.length && + (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0)) + return 0; /* false */ + ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); - return (ssh_gssapi_acquire_cred(*ctx)); -} + major = ssh_gssapi_import_name(*ctx, host); + if (!GSS_ERROR(major)) { + major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, + NULL); + gss_release_buffer(&minor, &token); + if ((*ctx)->context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&minor, &(*ctx)->context, + GSS_C_NO_BUFFER); + } + + if (GSS_ERROR(major) || intctx != NULL) + ssh_gssapi_delete_ctx(ctx); -int -ssh_gssapi_check_mechanism(gss_OID oid, void *host) { - Gssctxt * ctx = NULL; - gss_buffer_desc token = GSS_C_EMPTY_BUFFER; - OM_uint32 major, minor; - - ssh_gssapi_build_ctx(&ctx); - ssh_gssapi_set_oid(ctx, oid); - ssh_gssapi_import_name(ctx, host); - major = ssh_gssapi_init_ctx(ctx, 0, GSS_C_NO_BUFFER, &token, NULL); - gss_release_buffer(&minor, &token); - ssh_gssapi_delete_ctx(&ctx); return (!GSS_ERROR(major)); }