...

Text file src/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.c

Documentation: go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi

     1// Copyright (C) MongoDB, Inc. 2022-present.
     2//
     3// Licensed under the Apache License, Version 2.0 (the "License"); you may
     4// not use this file except in compliance with the License. You may obtain
     5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6
     7//+build gssapi
     8//+build linux darwin
     9
    10#include <string.h>
    11#include <stdio.h>
    12#include "gss_wrapper.h"
    13
    14OM_uint32 gssapi_canonicalize_name(
    15    OM_uint32* minor_status,
    16    char *input_name,
    17    gss_OID input_name_type,
    18    gss_name_t *output_name
    19)
    20{
    21    OM_uint32 major_status;
    22    gss_name_t imported_name = GSS_C_NO_NAME;
    23    gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
    24
    25    buffer.value = input_name;
    26    buffer.length = strlen(input_name);
    27    major_status = gss_import_name(minor_status, &buffer, input_name_type, &imported_name);
    28    if (GSS_ERROR(major_status)) {
    29        return major_status;
    30    }
    31
    32    major_status = gss_canonicalize_name(minor_status, imported_name, (gss_OID)gss_mech_krb5, output_name);
    33    if (imported_name != GSS_C_NO_NAME) {
    34        OM_uint32 ignored;
    35        gss_release_name(&ignored, &imported_name);
    36    }
    37
    38    return major_status;
    39}
    40
    41int gssapi_error_desc(
    42    OM_uint32 maj_stat,
    43    OM_uint32 min_stat,
    44    char **desc
    45)
    46{
    47    OM_uint32 stat = maj_stat;
    48    int stat_type = GSS_C_GSS_CODE;
    49    if (min_stat != 0) {
    50        stat = min_stat;
    51        stat_type = GSS_C_MECH_CODE;
    52    }
    53
    54    OM_uint32 local_maj_stat, local_min_stat;
    55    OM_uint32 msg_ctx = 0;
    56    gss_buffer_desc desc_buffer;
    57    do
    58    {
    59        local_maj_stat = gss_display_status(
    60            &local_min_stat,
    61            stat,
    62            stat_type,
    63            GSS_C_NO_OID,
    64            &msg_ctx,
    65            &desc_buffer
    66        );
    67        if (GSS_ERROR(local_maj_stat)) {
    68            return GSSAPI_ERROR;
    69        }
    70
    71        if (*desc) {
    72            free(*desc);
    73        }
    74
    75        *desc = malloc(desc_buffer.length+1);
    76        memcpy(*desc, desc_buffer.value, desc_buffer.length+1);
    77
    78        gss_release_buffer(&local_min_stat, &desc_buffer);
    79    }
    80    while(msg_ctx != 0);
    81
    82    return GSSAPI_OK;
    83}
    84
    85int gssapi_client_init(
    86    gssapi_client_state *client,
    87    char* spn,
    88    char* username,
    89    char* password
    90)
    91{
    92    client->cred = GSS_C_NO_CREDENTIAL;
    93    client->ctx = GSS_C_NO_CONTEXT;
    94
    95    client->maj_stat = gssapi_canonicalize_name(&client->min_stat, spn, GSS_C_NT_HOSTBASED_SERVICE, &client->spn);
    96    if (GSS_ERROR(client->maj_stat)) {
    97        return GSSAPI_ERROR;
    98    }
    99
   100    if (username) {
   101        gss_name_t name;
   102        client->maj_stat = gssapi_canonicalize_name(&client->min_stat, username, GSS_C_NT_USER_NAME, &name);
   103        if (GSS_ERROR(client->maj_stat)) {
   104            return GSSAPI_ERROR;
   105        }
   106
   107        if (password) {
   108            gss_buffer_desc password_buffer;
   109            password_buffer.value = password;
   110            password_buffer.length = strlen(password);
   111            client->maj_stat = gss_acquire_cred_with_password(&client->min_stat, name, &password_buffer, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
   112        } else {
   113            client->maj_stat = gss_acquire_cred(&client->min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
   114        }
   115
   116        if (GSS_ERROR(client->maj_stat)) {
   117            return GSSAPI_ERROR;
   118        }
   119
   120        OM_uint32 ignored;
   121        gss_release_name(&ignored, &name);
   122    }
   123
   124    return GSSAPI_OK;
   125}
   126
   127int gssapi_client_username(
   128    gssapi_client_state *client,
   129    char** username
   130)
   131{
   132    OM_uint32 ignored;
   133    gss_name_t name = GSS_C_NO_NAME;
   134
   135    client->maj_stat = gss_inquire_context(&client->min_stat, client->ctx, &name, NULL, NULL, NULL, NULL, NULL, NULL);
   136    if (GSS_ERROR(client->maj_stat)) {
   137        return GSSAPI_ERROR;
   138    }
   139
   140    gss_buffer_desc name_buffer;
   141    client->maj_stat = gss_display_name(&client->min_stat, name, &name_buffer, NULL);
   142    if (GSS_ERROR(client->maj_stat)) {
   143        gss_release_name(&ignored, &name);
   144        return GSSAPI_ERROR;
   145    }
   146
   147	*username = malloc(name_buffer.length+1);
   148	memcpy(*username, name_buffer.value, name_buffer.length+1);
   149
   150    gss_release_buffer(&ignored, &name_buffer);
   151    gss_release_name(&ignored, &name);
   152    return GSSAPI_OK;
   153}
   154
   155int gssapi_client_negotiate(
   156    gssapi_client_state *client,
   157    void* input,
   158    size_t input_length,
   159    void** output,
   160    size_t* output_length
   161)
   162{
   163    gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
   164    gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
   165
   166    if (input) {
   167        input_buffer.value = input;
   168        input_buffer.length = input_length;
   169    }
   170
   171    client->maj_stat = gss_init_sec_context(
   172        &client->min_stat,
   173        client->cred,
   174        &client->ctx,
   175        client->spn,
   176        GSS_C_NO_OID,
   177        GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
   178        0,
   179        GSS_C_NO_CHANNEL_BINDINGS,
   180        &input_buffer,
   181        NULL,
   182        &output_buffer,
   183        NULL,
   184        NULL
   185    );
   186
   187    if (output_buffer.length) {
   188        *output = malloc(output_buffer.length);
   189        *output_length = output_buffer.length;
   190        memcpy(*output, output_buffer.value, output_buffer.length);
   191
   192        OM_uint32 ignored;
   193        gss_release_buffer(&ignored, &output_buffer);
   194    }
   195
   196    if (GSS_ERROR(client->maj_stat)) {
   197        return GSSAPI_ERROR;
   198    } else if (client->maj_stat == GSS_S_CONTINUE_NEEDED) {
   199        return GSSAPI_CONTINUE;
   200    }
   201
   202    return GSSAPI_OK;
   203}
   204
   205int gssapi_client_wrap_msg(
   206    gssapi_client_state *client,
   207    void* input,
   208    size_t input_length,
   209    void** output,
   210    size_t* output_length
   211)
   212{
   213    gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
   214    gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
   215
   216    input_buffer.value = input;
   217    input_buffer.length = input_length;
   218
   219    client->maj_stat = gss_wrap(&client->min_stat, client->ctx, 0, GSS_C_QOP_DEFAULT, &input_buffer, NULL, &output_buffer);
   220
   221    if (output_buffer.length) {
   222        *output = malloc(output_buffer.length);
   223        *output_length = output_buffer.length;
   224        memcpy(*output, output_buffer.value, output_buffer.length);
   225
   226        gss_release_buffer(&client->min_stat, &output_buffer);
   227    }
   228
   229    if (GSS_ERROR(client->maj_stat)) {
   230        return GSSAPI_ERROR;
   231    }
   232
   233    return GSSAPI_OK;
   234}
   235
   236int gssapi_client_destroy(
   237    gssapi_client_state *client
   238)
   239{
   240    OM_uint32 ignored;
   241    if (client->ctx != GSS_C_NO_CONTEXT) {
   242        gss_delete_sec_context(&ignored, &client->ctx, GSS_C_NO_BUFFER);
   243    }
   244
   245    if (client->spn != GSS_C_NO_NAME) {
   246        gss_release_name(&ignored, &client->spn);
   247    }
   248
   249    if (client->cred != GSS_C_NO_CREDENTIAL) {
   250        gss_release_cred(&ignored, &client->cred);
   251    }
   252
   253    return GSSAPI_OK;
   254}

View as plain text