X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/7364bd04fc18484f99f74b901c4581795bcf2787..7bf7b86c4a72888673fbaf3c0ddc870b4cd4a555:/gss-genr.c diff --git a/gss-genr.c b/gss-genr.c index bda12d6f..e9190575 100644 --- a/gss-genr.c +++ b/gss-genr.c @@ -1,7 +1,7 @@ -/* $OpenBSD: gss-genr.c,v 1.1 2003/08/22 10:56:09 markus Exp $ */ +/* $OpenBSD: gss-genr.c,v 1.19 2007/06/12 11:56:15 dtucker 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 @@ -28,14 +28,22 @@ #ifdef GSSAPI +#include +#include + +#include +#include +#include + #include "xmalloc.h" -#include "bufaux.h" -#include "compat.h" +#include "buffer.h" #include "log.h" -#include "monitor_wrap.h" +#include "ssh2.h" #include "ssh-gss.h" +extern u_char *session_id2; +extern u_int session_id2_len; /* Check that the OID in a data stream matches that in the context */ int @@ -71,12 +79,16 @@ 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 * -ssh_gssapi_last_error(Gssctxt *ctxt, - OM_uint32 *major_status, OM_uint32 *minor_status) +ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, + OM_uint32 *minor_status) { OM_uint32 lmin; gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; @@ -95,7 +107,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, /* The GSSAPI error */ do { gss_display_status(&lmin, ctxt->major, - GSS_C_GSS_CODE, GSS_C_NULL_OID, &ctx, &msg); + GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg); buffer_append(&b, msg.value, msg.length); buffer_put_char(&b, '\n'); @@ -106,7 +118,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, /* The mechanism specific error */ do { gss_display_status(&lmin, ctxt->minor, - GSS_C_MECH_CODE, GSS_C_NULL_OID, &ctx, &msg); + GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg); buffer_append(&b, msg.value, msg.length); buffer_put_char(&b, '\n'); @@ -130,9 +142,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, 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; @@ -202,10 +212,11 @@ OM_uint32 ssh_gssapi_import_name(Gssctxt *ctx, const char *host) { gss_buffer_desc gssbuf; + char *val; - gssbuf.length = sizeof("host@") + strlen(host); - gssbuf.value = xmalloc(gssbuf.length); - snprintf(gssbuf.value, gssbuf.length, "host@%s", host); + xasprintf(&val, "host@%s", host); + gssbuf.value = val; + gssbuf.length = strlen(gssbuf.value); if ((ctx->major = gss_import_name(&ctx->minor, &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) @@ -215,42 +226,56 @@ 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) +ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { - 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))) + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, + GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); - gss_release_oid_set(&status, &oidset); return (ctx->major); } -OM_uint32 -ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { - if (*ctx) - ssh_gssapi_delete_ctx(ctx); +void +ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, + const char *context) +{ + buffer_init(b); + buffer_put_string(b, session_id2, session_id2_len); + buffer_put_char(b, SSH2_MSG_USERAUTH_REQUEST); + buffer_put_cstring(b, user); + buffer_put_cstring(b, service); + buffer_put_cstring(b, context); +} + +int +ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +{ + 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"}; + + /* 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)) + ssh_gssapi_delete_ctx(ctx); + + return (!GSS_ERROR(major)); } #endif /* GSSAPI */