X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/2ce0bfe419965b35c425fbf900bde08e27b8785a..944e4e582be802144f889cadee3077f1a2b8b950:/openssh/gss-genr.c diff --git a/openssh/gss-genr.c b/openssh/gss-genr.c index 4b891ac..9bc2a84 100644 --- a/openssh/gss-genr.c +++ b/openssh/gss-genr.c @@ -1,7 +1,7 @@ -/* $OpenBSD: gss-genr.c,v 1.4 2005/07/17 07:17:55 djm Exp $ */ +/* $OpenBSD: gss-genr.c,v 1.6 2005/10/13 22:24:31 stevesk Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,15 +29,11 @@ #ifdef GSSAPI #include "xmalloc.h" -#include "buffer.h" #include "bufaux.h" -#include "compat.h" -#include -#include "kex.h" #include "log.h" -#include "monitor_wrap.h" #include "canohost.h" #include "ssh2.h" +#include #include "ssh-gss.h" @@ -48,109 +44,139 @@ typedef struct { char *encoded; gss_OID oid; } ssh_gss_kex_mapping; - -static ssh_gss_kex_mapping *gss_enc2oid; -/* Return a list of the gss-group1-sha1-x mechanisms supported by this - * program. - * - * On the client side, we don't need to worry about whether we 'know' - * about the mechanism or not - we assume that any mechanism that we've been - * linked against is suitable for inclusion. +/* + * 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() { + return (gss_enc2oid != NULL); +} + +/* + * Return a list of the gss-group1-sha1 mechanisms supported by this program * - * XXX - We might want to make this configurable in the future, so as to - * XXX - allow the user control over which mechanisms to use. + * 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(char *host) { - gss_OID_set supported; - OM_uint32 min_status; - Buffer buf; - int i = 0; - char *mechs; - char *encoded; - int enclen; - char digest[EVP_MAX_MD_SIZE]; - char deroid[2]; - const EVP_MD *evp_md = EVP_md5(); - EVP_MD_CTX md; - int oidpos=0; - - gss_indicate_mechs(&min_status,&supported); - gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping) - *(supported->count+1)); - - buffer_init(&buf); - for (i=0;icount;i++) { - gss_enc2oid[oidpos].encoded=NULL; - - if (supported->elements[i].length<128 && - ssh_gssapi_check_mechanism(&(supported->elements[i]),host)) { +char * +ssh_gssapi_client_mechanisms(const char *host) { + gss_OID_set gss_supported; + OM_uint32 min_status; + + gss_indicate_mechs(&min_status, &gss_supported); - /* Add the required DER encoding octets and MD5 hash */ - deroid[0]=0x06; /* Object Identifier */ - deroid[1]=supported->elements[i].length; + return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, + (void *)host)); +} + +char * +ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, + void *data) { + 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++) + xfree(gss_enc2oid[i].encoded); + xfree(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)(&(gss_supported->elements[i]), data)) { + + 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, deroid, 2); EVP_DigestUpdate(&md, - supported->elements[i].elements, - supported->elements[i].length); + gss_supported->elements[i].elements, + gss_supported->elements[i].length); EVP_DigestFinal(&md, digest, NULL); - - /* Base64 encode it */ - 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_SHA1, sizeof(KEX_GSS_SHA1)-1); - buffer_append(&buf, encoded, enclen); - debug("Mechanism encoded as %s",encoded); + encoded = xmalloc(EVP_MD_size(evp_md)*2); + enclen = __b64_ntop(digest, EVP_MD_size(evp_md), + encoded, EVP_MD_size(evp_md)*2); - gss_enc2oid[oidpos].oid=&(supported->elements[i]); - gss_enc2oid[oidpos].encoded=encoded; + 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); + + 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)); + 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) - return(NULL); - else - return(mechs); -} -gss_OID -ssh_gssapi_client_id_kex(Gssctxt *ctx, char *name) { - int i=0; - - if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) !=0) { - return(NULL); + if (strlen(mechs) == 0) { + xfree(mechs); + mechs = NULL; } - name+=sizeof(KEX_GSS_SHA1)-1; /* Move to the start of the ID string */ - - while (gss_enc2oid[i].encoded!=NULL && - strcmp(name,gss_enc2oid[i].encoded)!=0) { - i++; + return (mechs); +} + +gss_OID +ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int *gex) { + 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; } - - if (gss_enc2oid[i].oid!=NULL) { - ssh_gssapi_set_oid(ctx,gss_enc2oid[i].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; } @@ -378,6 +404,9 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) 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); @@ -385,6 +414,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) return (ctx->major); } +/* Priviledged when used by server */ +OM_uint32 +ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +{ + if (ctx == NULL) + return -1; + + ctx->major = gss_verify_mic(&ctx->minor, ctx->context, + gssbuf, gssmic, NULL); + + return (ctx->major); +} + void ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, const char *context) @@ -398,7 +440,8 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, } OM_uint32 -ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { +ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) +{ if (*ctx) ssh_gssapi_delete_ctx(ctx); ssh_gssapi_build_ctx(ctx); @@ -407,18 +450,18 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { } int -ssh_gssapi_check_mechanism(gss_OID oid, const char *host) { +ssh_gssapi_check_mechanism(gss_OID oid, void *host) { Gssctxt * ctx = NULL; - gss_buffer_desc token; - OM_uint32 major,minor; + 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_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)); + return (!GSS_ERROR(major)); } #endif /* GSSAPI */