/*
- * Copyright (c) 2001 Simon Wilkinson. All rights reserved. *
+ * Copyright (c) 2001,2002 Simon Wilkinson. All rights reserved. *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
#include "kex.h"
#include "log.h"
#include "compat.h"
+#include "monitor_wrap.h"
#include <netdb.h>
gss_cred_id_t gssapi_client_creds = GSS_C_NO_CREDENTIAL; /* Their credentials */
enum ssh_gss_id gssapi_client_type = GSS_LAST_ENTRY;
+unsigned char ssh1_key_digest[16]; /* used for ssh1 gssapi */
+
/* The mechanism name used in the list below is defined in the internet
* draft as the Base 64 encoding of the MD5 hash of the ASN.1 DER encoding
* of the underlying GSSAPI mechanism's OID.
int i = 0;
int present;
char * mechs;
- Gssctxt ctx;
- gss_buffer_desc token;
+ Gssctxt * ctx = NULL;
if (datafellows & SSH_OLD_GSSAPI) return NULL;
present=0;
}
if (present) {
- ssh_gssapi_build_ctx(&ctx);
- ssh_gssapi_set_oid(&ctx,&supported_mechs[i].oid);
- if (server) {
- if (ssh_gssapi_acquire_cred(&ctx)) {
- ssh_gssapi_delete_ctx(&ctx);
- continue;
- }
- }
- else { /* client */
- if (ssh_gssapi_import_name(&ctx,host))
- continue;
- maj_status=ssh_gssapi_init_ctx(&ctx, 0,
- GSS_C_NO_BUFFER,
- &token,
- NULL);
- ssh_gssapi_delete_ctx(&ctx);
- if (GSS_ERROR(maj_status)) {
- continue;
- }
- }
-
- /* Append gss_group1_sha1_x to our list */
- buffer_append(&buf, gssprefix,
- strlen(gssprefix));
- buffer_append(&buf, supported_mechs[i].enc_name,
- strlen(supported_mechs[i].enc_name));
- }
+ if ((server &&
+ !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx,
+ &supported_mechs[i].oid))))
+ || (!server &&
+ !GSS_ERROR(ssh_gssapi_client_ctx(&ctx,
+ &supported_mechs[i].oid,
+ host)))) {
+ /* Append gss_group1_sha1_x to our list */
+ buffer_append(&buf, gssprefix,
+ strlen(gssprefix));
+ buffer_append(&buf,
+ supported_mechs[i].enc_name,
+ strlen(supported_mechs[i].enc_name));
+ }
+ }
} while (supported_mechs[++i].name != NULL);
buffer_put_char(&buf,'\0');
/* Set the GSS context's OID to the oid indicated by the given key exchange
* name. */
-int ssh_gssapi_id_kex(Gssctxt *ctx, char *name) {
+gss_OID ssh_gssapi_id_kex(Gssctxt *ctx, char *name) {
enum ssh_gss_id i=0;
if (strncmp(name, gssprefix, strlen(gssprefix)-1) !=0) {
- return(1);
+ return(NULL);
}
name+=strlen(gssprefix); /* Move to the start of the MIME string */
}
if (supported_mechs[i].name==NULL)
- return (1);
+ return (NULL);
- ssh_gssapi_set_oid(ctx,&supported_mechs[i].oid);
+ if (ctx) ssh_gssapi_set_oid(ctx,&supported_mechs[i].oid);
- return 0;
+ return &supported_mechs[i].oid;
}
* stuff life is a little easier
*/
void
-ssh_gssapi_build_ctx(Gssctxt *ctx)
+ssh_gssapi_build_ctx(Gssctxt **ctx)
{
- ctx->context=GSS_C_NO_CONTEXT;
- ctx->name=GSS_C_NO_NAME;
- ctx->oid=GSS_C_NO_OID;
- ctx->creds=GSS_C_NO_CREDENTIAL;
- ctx->client=GSS_C_NO_NAME;
- ctx->client_creds=GSS_C_NO_CREDENTIAL;
+ *ctx=xmalloc(sizeof (Gssctxt));
+ (*ctx)->context=GSS_C_NO_CONTEXT;
+ (*ctx)->name=GSS_C_NO_NAME;
+ (*ctx)->oid=GSS_C_NO_OID;
+ (*ctx)->creds=GSS_C_NO_CREDENTIAL;
+ (*ctx)->client=GSS_C_NO_NAME;
+ (*ctx)->client_creds=GSS_C_NO_CREDENTIAL;
}
/* Delete our context, providing it has been built correctly */
void
-ssh_gssapi_delete_ctx(Gssctxt *ctx)
+ssh_gssapi_delete_ctx(Gssctxt **ctx)
{
OM_uint32 ms;
- if (ctx->context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&ms,&ctx->context,GSS_C_NO_BUFFER);
- if (ctx->name != GSS_C_NO_NAME)
- gss_release_name(&ms,&ctx->name);
- if (ctx->oid != GSS_C_NO_OID) {
- xfree(ctx->oid->elements);
- xfree(ctx->oid);
- ctx->oid = GSS_C_NO_OID;
+ /* Return if there's no context */
+ if ((*ctx)==NULL)
+ return;
+
+ if ((*ctx)->context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&ms,&(*ctx)->context,GSS_C_NO_BUFFER);
+ if ((*ctx)->name != GSS_C_NO_NAME)
+ gss_release_name(&ms,&(*ctx)->name);
+ if ((*ctx)->oid != GSS_C_NO_OID) {
+ xfree((*ctx)->oid->elements);
+ xfree((*ctx)->oid);
+ (*ctx)->oid = GSS_C_NO_OID;
}
- if (ctx->creds != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&ms,&ctx->creds);
- if (ctx->client != GSS_C_NO_NAME)
- gss_release_name(&ms,&ctx->client);
- if (ctx->client_creds != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&ms,&ctx->client_creds);
+ if ((*ctx)->creds != GSS_C_NO_CREDENTIAL)
+ gss_release_cred(&ms,&(*ctx)->creds);
+ if ((*ctx)->client != GSS_C_NO_NAME)
+ gss_release_name(&ms,&(*ctx)->client);
+ if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL)
+ gss_release_cred(&ms,&(*ctx)->client_creds);
+
+ xfree(*ctx);
+ *ctx=NULL;
}
/* Wrapper to init_sec_context
debug("Got no client credentials");
}
- /* FIXME: We should check that the mechanism thats being used is
+ /* FIXME: We should check that the me
* the one that we asked for (in ctx->oid) */
ctx->status=maj_status;
+ /* Now, if we're complete and we have the right flags, then
+ * we flag the user as also having been authenticated
+ */
+
+ if (((flags==NULL) || ((*flags & GSS_C_MUTUAL_FLAG) &&
+ (*flags & GSS_C_INTEG_FLAG))) &&
+ (maj_status == GSS_S_COMPLETE)) {
+ if (ssh_gssapi_getclient(ctx,&gssapi_client_type,
+ &gssapi_client_name,
+ &gssapi_client_creds))
+ fatal("Couldn't convert client name");
+ }
+
return(maj_status);
}
/* 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 maj_status, min_status;
ctx->client_creds=GSS_C_NO_CREDENTIAL;
return(maj_status);
}
+
+OM_uint32
+ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *buffer, gss_buffer_desc *hash) {
+ OM_uint32 maj_status,min_status;
+ /* ssh1 needs to exchange the hash of the keys */
+ /* will us this hash to return it */
+ if (!compat20) {
+ if ((maj_status=gss_wrap(&min_status,ctx->context,
+ 0,
+ GSS_C_QOP_DEFAULT,
+ buffer,
+ NULL,
+ hash)))
+ ssh_gssapi_error(maj_status,min_status);
+ }
+ else
+
+ if ((maj_status=gss_get_mic(&min_status,ctx->context,
+ GSS_C_QOP_DEFAULT, buffer, hash))) {
+ ssh_gssapi_error(maj_status,min_status);
+ }
+
+ return(maj_status);
+}
+
+OM_uint32
+ssh_gssapi_server_ctx(Gssctxt **ctx,gss_OID oid) {
+ if (*ctx) ssh_gssapi_delete_ctx(ctx);
+ ssh_gssapi_build_ctx(ctx);
+ ssh_gssapi_set_oid(*ctx,oid);
+ return(ssh_gssapi_acquire_cred(*ctx));
+}
+
+OM_uint32
+ssh_gssapi_client_ctx(Gssctxt **ctx,gss_OID oid, char *host) {
+ gss_buffer_desc token;
+ OM_uint32 major,minor;
+
+ if (*ctx) ssh_gssapi_delete_ctx(ctx);
+ 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);
+ return(major);
+}
+
#endif /* GSSAPI */