summaryrefslogtreecommitdiff
path: root/src/transports/auth_negotiate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transports/auth_negotiate.c')
-rw-r--r--src/transports/auth_negotiate.c315
1 files changed, 0 insertions, 315 deletions
diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c
deleted file mode 100644
index 31469933e..000000000
--- a/src/transports/auth_negotiate.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "auth_negotiate.h"
-
-#if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK)
-
-#include "git2.h"
-#include "buffer.h"
-#include "auth.h"
-#include "git2/sys/credential.h"
-
-#ifdef GIT_GSSFRAMEWORK
-#import <GSS/GSS.h>
-#elif defined(GIT_GSSAPI)
-#include <gssapi.h>
-#include <krb5.h>
-#endif
-
-static gss_OID_desc negotiate_oid_spnego =
- { 6, (void *) "\x2b\x06\x01\x05\x05\x02" };
-static gss_OID_desc negotiate_oid_krb5 =
- { 9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
-
-static gss_OID negotiate_oids[] =
- { &negotiate_oid_spnego, &negotiate_oid_krb5, NULL };
-
-typedef struct {
- git_http_auth_context parent;
- unsigned configured : 1,
- complete : 1;
- git_buf target;
- char *challenge;
- gss_ctx_id_t gss_context;
- gss_OID oid;
-} http_auth_negotiate_context;
-
-static void negotiate_err_set(
- OM_uint32 status_major,
- OM_uint32 status_minor,
- const char *message)
-{
- gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
- OM_uint32 status_display, context = 0;
-
- if (gss_display_status(&status_display, status_major, GSS_C_GSS_CODE,
- GSS_C_NO_OID, &context, &buffer) == GSS_S_COMPLETE) {
- git_error_set(GIT_ERROR_NET, "%s: %.*s (%d.%d)",
- message, (int)buffer.length, (const char *)buffer.value,
- status_major, status_minor);
- gss_release_buffer(&status_minor, &buffer);
- } else {
- git_error_set(GIT_ERROR_NET, "%s: unknown negotiate error (%d.%d)",
- message, status_major, status_minor);
- }
-}
-
-static int negotiate_set_challenge(
- git_http_auth_context *c,
- const char *challenge)
-{
- http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
-
- GIT_ASSERT_ARG(ctx);
- GIT_ASSERT_ARG(challenge);
- GIT_ASSERT(ctx->configured);
-
- git__free(ctx->challenge);
-
- ctx->challenge = git__strdup(challenge);
- GIT_ERROR_CHECK_ALLOC(ctx->challenge);
-
- return 0;
-}
-
-static void negotiate_context_dispose(http_auth_negotiate_context *ctx)
-{
- OM_uint32 status_minor;
-
- if (ctx->gss_context != GSS_C_NO_CONTEXT) {
- gss_delete_sec_context(
- &status_minor, &ctx->gss_context, GSS_C_NO_BUFFER);
- ctx->gss_context = GSS_C_NO_CONTEXT;
- }
-
- git_buf_dispose(&ctx->target);
-
- git__free(ctx->challenge);
- ctx->challenge = NULL;
-}
-
-static int negotiate_next_token(
- git_buf *buf,
- git_http_auth_context *c,
- git_credential *cred)
-{
- http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
- OM_uint32 status_major, status_minor;
- gss_buffer_desc target_buffer = GSS_C_EMPTY_BUFFER,
- input_token = GSS_C_EMPTY_BUFFER,
- output_token = GSS_C_EMPTY_BUFFER;
- gss_buffer_t input_token_ptr = GSS_C_NO_BUFFER;
- git_buf input_buf = GIT_BUF_INIT;
- gss_name_t server = NULL;
- gss_OID mech;
- size_t challenge_len;
- int error = 0;
-
- GIT_ASSERT_ARG(buf);
- GIT_ASSERT_ARG(ctx);
- GIT_ASSERT_ARG(cred);
-
- GIT_ASSERT(ctx->configured);
- GIT_ASSERT(cred->credtype == GIT_CREDENTIAL_DEFAULT);
-
- if (ctx->complete)
- return 0;
-
- target_buffer.value = (void *)ctx->target.ptr;
- target_buffer.length = ctx->target.size;
-
- status_major = gss_import_name(&status_minor, &target_buffer,
- GSS_C_NT_HOSTBASED_SERVICE, &server);
-
- if (GSS_ERROR(status_major)) {
- negotiate_err_set(status_major, status_minor,
- "could not parse principal");
- error = -1;
- goto done;
- }
-
- challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0;
-
- if (challenge_len < 9 || memcmp(ctx->challenge, "Negotiate", 9) != 0) {
- git_error_set(GIT_ERROR_NET, "server did not request negotiate");
- error = -1;
- goto done;
- }
-
- if (challenge_len > 9) {
- if (git_buf_decode_base64(&input_buf,
- ctx->challenge + 10, challenge_len - 10) < 0) {
- git_error_set(GIT_ERROR_NET, "invalid negotiate challenge from server");
- error = -1;
- goto done;
- }
-
- input_token.value = input_buf.ptr;
- input_token.length = input_buf.size;
- input_token_ptr = &input_token;
- } else if (ctx->gss_context != GSS_C_NO_CONTEXT) {
- negotiate_context_dispose(ctx);
- }
-
- mech = &negotiate_oid_spnego;
-
- status_major = gss_init_sec_context(
- &status_minor,
- GSS_C_NO_CREDENTIAL,
- &ctx->gss_context,
- server,
- mech,
- GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG,
- GSS_C_INDEFINITE,
- GSS_C_NO_CHANNEL_BINDINGS,
- input_token_ptr,
- NULL,
- &output_token,
- NULL,
- NULL);
-
- if (GSS_ERROR(status_major)) {
- negotiate_err_set(status_major, status_minor, "negotiate failure");
- error = -1;
- goto done;
- }
-
- /* This message merely told us auth was complete; we do not respond. */
- if (status_major == GSS_S_COMPLETE) {
- negotiate_context_dispose(ctx);
- ctx->complete = 1;
- goto done;
- }
-
- if (output_token.length == 0) {
- git_error_set(GIT_ERROR_NET, "GSSAPI did not return token");
- error = -1;
- goto done;
- }
-
- git_buf_puts(buf, "Negotiate ");
- git_buf_encode_base64(buf, output_token.value, output_token.length);
-
- if (git_buf_oom(buf))
- error = -1;
-
-done:
- gss_release_name(&status_minor, &server);
- gss_release_buffer(&status_minor, (gss_buffer_t) &output_token);
- git_buf_dispose(&input_buf);
- return error;
-}
-
-static int negotiate_is_complete(git_http_auth_context *c)
-{
- http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
-
- GIT_ASSERT_ARG(ctx);
-
- return (ctx->complete == 1);
-}
-
-static void negotiate_context_free(git_http_auth_context *c)
-{
- http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
-
- negotiate_context_dispose(ctx);
-
- ctx->configured = 0;
- ctx->complete = 0;
- ctx->oid = NULL;
-
- git__free(ctx);
-}
-
-static int negotiate_init_context(
- http_auth_negotiate_context *ctx,
- const git_net_url *url)
-{
- OM_uint32 status_major, status_minor;
- gss_OID item, *oid;
- gss_OID_set mechanism_list;
- size_t i;
-
- /* Query supported mechanisms looking for SPNEGO) */
- status_major = gss_indicate_mechs(&status_minor, &mechanism_list);
-
- if (GSS_ERROR(status_major)) {
- negotiate_err_set(status_major, status_minor,
- "could not query mechanisms");
- return -1;
- }
-
- if (mechanism_list) {
- for (oid = negotiate_oids; *oid; oid++) {
- for (i = 0; i < mechanism_list->count; i++) {
- item = &mechanism_list->elements[i];
-
- if (item->length == (*oid)->length &&
- memcmp(item->elements, (*oid)->elements, item->length) == 0) {
- ctx->oid = *oid;
- break;
- }
-
- }
-
- if (ctx->oid)
- break;
- }
- }
-
- gss_release_oid_set(&status_minor, &mechanism_list);
-
- if (!ctx->oid) {
- git_error_set(GIT_ERROR_NET, "negotiate authentication is not supported");
- return GIT_EAUTH;
- }
-
- git_buf_puts(&ctx->target, "HTTP@");
- git_buf_puts(&ctx->target, url->host);
-
- if (git_buf_oom(&ctx->target))
- return -1;
-
- ctx->gss_context = GSS_C_NO_CONTEXT;
- ctx->configured = 1;
-
- return 0;
-}
-
-int git_http_auth_negotiate(
- git_http_auth_context **out,
- const git_net_url *url)
-{
- http_auth_negotiate_context *ctx;
-
- *out = NULL;
-
- ctx = git__calloc(1, sizeof(http_auth_negotiate_context));
- GIT_ERROR_CHECK_ALLOC(ctx);
-
- if (negotiate_init_context(ctx, url) < 0) {
- git__free(ctx);
- return -1;
- }
-
- ctx->parent.type = GIT_HTTP_AUTH_NEGOTIATE;
- ctx->parent.credtypes = GIT_CREDENTIAL_DEFAULT;
- ctx->parent.connection_affinity = 1;
- ctx->parent.set_challenge = negotiate_set_challenge;
- ctx->parent.next_token = negotiate_next_token;
- ctx->parent.is_complete = negotiate_is_complete;
- ctx->parent.free = negotiate_context_free;
-
- *out = (git_http_auth_context *)ctx;
-
- return 0;
-}
-
-#endif /* GIT_GSSAPI */
-