LCOV - code coverage report
Current view: top level - src/tds - gssapi.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 0 250 0.0 %
Date: 2025-12-12 14:13:32 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 2007-2011  Frediano Ziglio
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : 
      22             : #if HAVE_STDLIB_H
      23             : #include <stdlib.h>
      24             : #endif /* HAVE_STDLIB_H */
      25             : 
      26             : #include <ctype.h>
      27             : 
      28             : #if HAVE_STRING_H
      29             : #include <string.h>
      30             : #endif /* HAVE_STRING_H */
      31             : 
      32             : #if HAVE_UNISTD_H
      33             : #include <unistd.h>
      34             : #endif /* HAVE_UNISTD_H */
      35             : 
      36             : #if HAVE_NETDB_H
      37             : #include <netdb.h>
      38             : #endif /* HAVE_NETDB_H */
      39             : 
      40             : #if HAVE_SYS_SOCKET_H
      41             : #include <sys/socket.h>
      42             : #endif /* HAVE_SYS_SOCKET_H */
      43             : 
      44             : #if HAVE_SYS_TYPES_H
      45             : #include <sys/types.h>
      46             : #endif /* HAVE_SYS_TYPES_H */
      47             : 
      48             : #if HAVE_NETINET_IN_H
      49             : #include <netinet/in.h>
      50             : #endif /* HAVE_NETINET_IN_H */
      51             : 
      52             : #if HAVE_ARPA_INET_H
      53             : #include <arpa/inet.h>
      54             : #endif /* HAVE_ARPA_INET_H */
      55             : 
      56             : #if HAVE_COM_ERR_H
      57             : #include <com_err.h>
      58             : #endif /* HAVE_COM_ERR_H */
      59             : 
      60             : #ifdef ENABLE_KRB5
      61             : 
      62             : #ifdef __APPLE__
      63             : #define KERBEROS_APPLE_DEPRECATED(x)
      64             : #define GSSKRB_APPLE_DEPRECATED(x)
      65             : #undef __API_DEPRECATED
      66             : #define __API_DEPRECATED(x, y)
      67             : #endif
      68             : #include <gssapi/gssapi_krb5.h>
      69             : 
      70             : #include <freetds/tds.h>
      71             : #include <freetds/utils/string.h>
      72             : #include <freetds/replacements.h>
      73             : #include <freetds/tls.h>
      74             : 
      75             : /**
      76             :  * \ingroup libtds
      77             :  * \defgroup auth Authentication
      78             :  * Functions for handling authentication.
      79             :  */
      80             : 
      81             : /**
      82             :  * \addtogroup auth
      83             :  * @{ 
      84             :  */
      85             : 
      86             : typedef struct tds_gss_auth
      87             : {
      88             :         TDSAUTHENTICATION tds_auth;
      89             :         gss_ctx_id_t gss_context;
      90             :         gss_name_t target_name;
      91             :         char *sname;
      92             :         OM_uint32 last_stat;
      93             : } TDSGSSAUTH;
      94             : 
      95             : static TDSRET
      96           0 : tds_gss_free(TDSCONNECTION *conn TDS_UNUSED, TDSAUTHENTICATION *tds_auth)
      97             : {
      98           0 :         TDSGSSAUTH *auth = (TDSGSSAUTH *) tds_auth;
      99             :         OM_uint32 min_stat;
     100             : 
     101           0 :         if (auth->tds_auth.packet) {
     102             :                 gss_buffer_desc send_tok;
     103             : 
     104           0 :                 send_tok.value = (void *) auth->tds_auth.packet;
     105           0 :                 send_tok.length = auth->tds_auth.packet_len;
     106           0 :                 gss_release_buffer(&min_stat, &send_tok);
     107             :         }
     108             : 
     109           0 :         gss_release_name(&min_stat, &auth->target_name);
     110           0 :         free(auth->sname);
     111           0 :         if (auth->gss_context != GSS_C_NO_CONTEXT)
     112           0 :                 gss_delete_sec_context(&min_stat, &auth->gss_context, GSS_C_NO_BUFFER);
     113           0 :         free(auth);
     114             : 
     115           0 :         return TDS_SUCCESS;
     116             : }
     117             : 
     118             : static TDSRET tds_gss_continue(TDSSOCKET * tds, TDSGSSAUTH * auth, gss_buffer_desc * token_ptr);
     119             : 
     120             : static TDSRET
     121           0 : tds7_gss_handle_next(TDSSOCKET *tds, TDSAUTHENTICATION *auth, size_t len)
     122             : {
     123             :         TDSRET res;
     124             :         gss_buffer_desc recv_tok;
     125             : 
     126           0 :         if (((TDSGSSAUTH *) auth)->last_stat != GSS_S_CONTINUE_NEEDED)
     127             :                 return TDS_FAIL;
     128             : 
     129           0 :         if (auth->packet) {
     130             :                 OM_uint32 min_stat;
     131             :                 gss_buffer_desc send_tok;
     132             : 
     133           0 :                 send_tok.value = (void *) auth->packet;
     134           0 :                 send_tok.length = auth->packet_len;
     135           0 :                 gss_release_buffer(&min_stat, &send_tok);
     136           0 :                 auth->packet = NULL;
     137             :         }
     138             : 
     139           0 :         recv_tok.length = len;
     140           0 :         recv_tok.value = tds_new(char, len);
     141           0 :         if (!recv_tok.value)
     142             :                 return TDS_FAIL;
     143           0 :         tds_get_n(tds, recv_tok.value, len);
     144             : 
     145           0 :         res = tds_gss_continue(tds, (TDSGSSAUTH *) auth, &recv_tok);
     146           0 :         free(recv_tok.value);
     147           0 :         TDS_PROPAGATE(res);
     148             : 
     149           0 :         if (auth->packet_len) {
     150           0 :                 tds->out_flag = TDS7_AUTH;
     151           0 :                 tds_put_n(tds, auth->packet, auth->packet_len);
     152           0 :                 return tds_flush_packet(tds);
     153             :         }
     154             :         return TDS_SUCCESS;
     155             : }
     156             : 
     157             : static TDSRET
     158           0 : tds5_gss_handle_next(TDSSOCKET *tds, TDSAUTHENTICATION *auth, size_t len TDS_UNUSED)
     159             : {
     160             :         gss_buffer_desc recv_tok;
     161             :         TDSPARAMINFO *info;
     162             :         TDSCOLUMN *col;
     163             : 
     164           0 :         if (((TDSGSSAUTH *) auth)->last_stat != GSS_S_CONTINUE_NEEDED)
     165             :                 return TDS_FAIL;
     166             : 
     167           0 :         if (auth->packet) {
     168             :                 OM_uint32 min_stat;
     169             :                 gss_buffer_desc send_tok;
     170             : 
     171           0 :                 send_tok.value = (void *) auth->packet;
     172           0 :                 send_tok.length = auth->packet_len;
     173           0 :                 gss_release_buffer(&min_stat, &send_tok);
     174           0 :                 auth->packet = NULL;
     175             :         }
     176             : 
     177             :         /* parse from saved message */
     178           0 :         if (auth->msg_type != TDS5_MSG_SEC_OPAQUE)
     179             :                 goto error;
     180           0 :         auth->msg_type = 0;
     181             : 
     182           0 :         info = tds->param_info;
     183           0 :         if (!info || info->num_cols < 5)
     184             :                 goto error;
     185             : 
     186             :         /* check first column is int and TDS5_SEC_VERSION */
     187           0 :         col = info->columns[0];
     188           0 :         if (tds_get_conversion_type(col->on_server.column_type, col->on_server.column_size) != SYBINT4)
     189             :                 goto error;
     190           0 :         if (*((TDS_INT *) col->column_data) != TDS5_SEC_VERSION)
     191             :                 goto error;
     192             : 
     193             :         /* check second column is int and TDS5_SEC_SECSESS */
     194           0 :         col = info->columns[1];
     195           0 :         if (tds_get_conversion_type(col->on_server.column_type, col->on_server.column_size) != SYBINT4)
     196             :                 goto error;
     197           0 :         if (*((TDS_INT *) col->column_data) != TDS5_SEC_SECSESS)
     198             :                 goto error;
     199             : 
     200           0 :         col = info->columns[3];
     201           0 :         if (col->column_type != SYBLONGBINARY)
     202             :                 goto error;
     203           0 :         recv_tok.value = ((TDSBLOB*) col->column_data)->textvalue;
     204           0 :         recv_tok.length = col->column_size;
     205             : 
     206           0 :         TDS_PROPAGATE(tds_gss_continue(tds, (TDSGSSAUTH *) auth, &recv_tok));
     207             : 
     208           0 :         tds->out_flag = TDS_NORMAL;
     209           0 :         TDS_PROPAGATE(tds5_gss_send(tds));
     210             : 
     211           0 :         return tds_flush_packet(tds);
     212             : 
     213           0 : error:
     214             :         return TDS_FAIL;
     215             : }
     216             : 
     217             : /**
     218             :  * Build a GSSAPI packet to send to server
     219             :  * @param tds     A pointer to the TDSSOCKET structure managing a client/server operation.
     220             :  * @return size of packet
     221             :  */
     222             : TDSAUTHENTICATION * 
     223           0 : tds_gss_get_auth(TDSSOCKET * tds)
     224             : {
     225             :         /*
     226             :          * TODO
     227             :          * There are some differences between this implementation and MS on
     228             :          * - MS use SPNEGO with 3 mechnisms (MS KRB5, KRB5, NTLMSSP)
     229             :          * - MS seems to use MUTUAL flag
     230             :          * - name type is "Service and Instance (2)" and not "Principal (1)"
     231             :          * check for memory leaks
     232             :          * check for errors in many functions
     233             :          * a bit more verbose
     234             :          * dinamically load library ??
     235             :          */
     236             :         gss_buffer_desc send_tok;
     237             :         OM_uint32 maj_stat, min_stat;
     238             : #ifdef __APPLE__
     239             :         /* some MacOS header defines gss_OID_desc with a wrong byte alignment, use external
     240             :          * library definition. */
     241             : #  define nt_principal (*(gss_OID_desc *) GSS_KRB5_NT_PRINCIPAL_NAME)
     242             : #else
     243             :         /* same as GSS_KRB5_NT_PRINCIPAL_NAME but do not require .so library */
     244             :         static gss_OID_desc nt_principal = { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01" };
     245             : #endif
     246             :         const char *server_name;
     247             :         const char *realm_separator, *realm;
     248             :         /* Storage for getaddrinfo calls */
     249           0 :         struct addrinfo *addrs = NULL;
     250           0 :         int len = 0;
     251             : 
     252             :         TDSGSSAUTH *auth;
     253             : 
     254           0 :         if (!tds->login)
     255             :                 return NULL;
     256             : 
     257           0 :         auth = tds_new0(TDSGSSAUTH, 1);
     258           0 :         if (!auth)
     259             :                 return NULL;
     260             : 
     261           0 :         auth->tds_auth.free = tds_gss_free;
     262           0 :         auth->tds_auth.handle_next = IS_TDS50(tds->conn) ? tds5_gss_handle_next : tds7_gss_handle_next;
     263           0 :         auth->gss_context = GSS_C_NO_CONTEXT;
     264           0 :         auth->last_stat = GSS_S_COMPLETE;
     265             : 
     266           0 :         server_name = tds_dstr_cstr(&tds->login->server_host_name);
     267           0 :         if (IS_TDS7_PLUS(tds->conn) && strchr(server_name, '.') == NULL) {
     268             :                 struct addrinfo hints;
     269           0 :                 memset(&hints, 0, sizeof(hints));
     270             :                 hints.ai_family = AF_UNSPEC;
     271           0 :                 hints.ai_socktype = SOCK_STREAM;
     272           0 :                 hints.ai_flags = AI_V4MAPPED|AI_ADDRCONFIG|AI_CANONNAME|AI_FQDN;
     273           0 :                 if (!getaddrinfo(server_name, NULL, &hints, &addrs) && addrs->ai_canonname
     274           0 :                     && strchr(addrs->ai_canonname, '.') != NULL)
     275           0 :                         server_name = addrs->ai_canonname;
     276             :         }
     277             : 
     278           0 :         if (!tds_dstr_isempty(&tds->login->server_realm_name)) {
     279           0 :                 realm_separator = "@";
     280           0 :                 realm = tds_dstr_cstr(&tds->login->server_realm_name);
     281             :         } else {
     282             :                 realm_separator = "";
     283             :                 realm = "";
     284             :         }
     285           0 :         if (!tds_dstr_isempty(&tds->login->server_spn)) {
     286           0 :                 auth->sname = strdup(tds_dstr_cstr(&tds->login->server_spn));
     287           0 :         } else if (IS_TDS7_PLUS(tds->conn)) {
     288           0 :                 if (!tds_dstr_isempty(&tds->login->instance_name)) {
     289           0 :                         len = asprintf(&auth->sname, "MSSQLSvc/%s:%s%s%s", server_name, tds_dstr_cstr(&tds->login->instance_name),
     290             :                                        realm_separator, realm);
     291             :                 } else {
     292           0 :                         len = asprintf(&auth->sname, "MSSQLSvc/%s:%d%s%s", server_name, tds->login->port, realm_separator, realm);
     293             :                 }
     294             :         } else {
     295             :                 /* TDS 5.0, Sybase */
     296           0 :                 server_name = tds_dstr_cstr(&tds->login->server_name);
     297           0 :                 len = asprintf(&auth->sname, "%s%s%s", server_name, realm_separator, realm);
     298             :         }
     299           0 :         if (addrs)
     300           0 :                 freeaddrinfo(addrs);
     301           0 :         if (len < 0 || auth->sname == NULL) {
     302           0 :                 tds_gss_free(tds->conn, (TDSAUTHENTICATION *) auth);
     303           0 :                 return NULL;
     304             :         }
     305           0 :         tdsdump_log(TDS_DBG_NETWORK, "using kerberos name %s\n", auth->sname);
     306             : 
     307             :         /*
     308             :          * Import the name into target_name.  Use send_tok to save
     309             :          * local variable space.
     310             :          */
     311           0 :         send_tok.value = auth->sname;
     312           0 :         send_tok.length = strlen(auth->sname);
     313           0 :         maj_stat = gss_import_name(&min_stat, &send_tok, &nt_principal, &auth->target_name);
     314             : 
     315           0 :         switch (maj_stat) {
     316           0 :         case GSS_S_COMPLETE: 
     317           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_COMPLETE: gss_import_name completed successfully.\n");
     318           0 :                 if (TDS_FAILED(tds_gss_continue(tds, auth, GSS_C_NO_BUFFER))) {
     319           0 :                         tds_gss_free(tds->conn, (TDSAUTHENTICATION *) auth);
     320           0 :                         return NULL;
     321             :                 }
     322             :                 break;
     323           0 :         case GSS_S_BAD_NAMETYPE: 
     324           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_BAD_NAMETYPE: The input_name_type was unrecognized.\n");
     325             :                 break;
     326           0 :         case GSS_S_BAD_NAME: 
     327           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_BAD_NAME: The input_name parameter could not be interpreted as a name of the specified type.\n");
     328             :                 break;
     329           0 :         case GSS_S_BAD_MECH:
     330           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_BAD_MECH: The input name-type was GSS_C_NT_EXPORT_NAME, but the mechanism contained within the input-name is not supported.\n");
     331             :                 break;
     332           0 :         default:
     333           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: unexpected error %d.\n", maj_stat);
     334             :                 break;
     335             :         }
     336             : 
     337           0 :         if (GSS_ERROR(maj_stat)) {
     338           0 :                 tds_gss_free(tds->conn, (TDSAUTHENTICATION *) auth);
     339           0 :                 return NULL;
     340             :         }
     341             : 
     342             :         return (TDSAUTHENTICATION *) auth;
     343             : }
     344             : 
     345             : #ifndef HAVE_ERROR_MESSAGE
     346             : static const char *
     347             : tds_error_message(OM_uint32 e)
     348             : {
     349           0 :         const char *m = strerror(e);
     350           0 :         if (m == NULL)
     351             :                 return "";
     352             :         return m;
     353             : }
     354             : #define error_message tds_error_message
     355             : #endif
     356             : 
     357             : static gss_channel_bindings_t
     358           0 : tds_gss_get_channel_binding(TDSSOCKET *tds)
     359             : {
     360             :         /* Get tls-unique from OpenSSL */
     361             :         unsigned char tls_unique_buf[256];
     362             :         size_t tls_unique_len;
     363             :         gss_channel_bindings_t cb;
     364             : 
     365           0 :         tls_unique_len = tds_ssl_get_cb(tds->conn, tls_unique_buf, sizeof(tls_unique_buf));
     366           0 :         if (tls_unique_len == 0)
     367             :                 return GSS_C_NO_CHANNEL_BINDINGS;
     368             : 
     369           0 :         cb = calloc(sizeof(struct gss_channel_bindings_struct) + 11 + tls_unique_len, sizeof(char));
     370             : 
     371           0 :         if (!cb) {
     372           0 :                 tdsdump_log(TDS_DBG_NETWORK, "tds_gss_get_channel_binding: failed to allocate channel bindings\n");
     373             :                 return GSS_C_NO_CHANNEL_BINDINGS;
     374             :         }
     375             : 
     376           0 :         cb->initiator_addrtype = GSS_C_AF_UNSPEC;
     377           0 :         cb->initiator_address.length = 0;
     378           0 :         cb->acceptor_addrtype = GSS_C_AF_UNSPEC;
     379           0 :         cb->acceptor_address.length = 0;
     380           0 :         cb->application_data.value = (void *) (cb + 1);
     381             : 
     382           0 :         cb->application_data.length = tls_unique_len + 11;
     383             : 
     384           0 :         memcpy(cb->application_data.value, "tls-unique:", 11);
     385           0 :         memcpy((char *) cb->application_data.value + 11, tls_unique_buf, tls_unique_len);
     386             : 
     387           0 :         tdsdump_dump_buf(TDS_DBG_NETWORK, "gss_channel_bindings_struct", cb, sizeof(struct gss_channel_bindings_struct));
     388           0 :         tdsdump_dump_buf(TDS_DBG_NETWORK,
     389           0 :                          "gss_channel_bindings_struct.application_data", cb->application_data.value, cb->application_data.length);
     390             :         return cb;
     391             : }
     392             : 
     393             : static TDSRET
     394           0 : tds_gss_continue(TDSSOCKET *tds, TDSGSSAUTH *auth, gss_buffer_desc *token_ptr)
     395             : {
     396             :         gss_buffer_desc send_tok;
     397           0 :         OM_uint32 maj_stat, min_stat = 0;
     398             :         OM_uint32 ret_flags;
     399             :         int gssapi_flags;
     400           0 :         const char *msg = "???";
     401           0 :         gss_OID pmech = GSS_C_NULL_OID;
     402             :         gss_channel_bindings_t cb;
     403             : 
     404           0 :         auth->last_stat = GSS_S_COMPLETE;
     405             : 
     406           0 :         send_tok.value = NULL;
     407           0 :         send_tok.length = 0;
     408             : 
     409             :         /*
     410             :          * Perform the context-establishement loop.
     411             :          *
     412             :          * On each pass through the loop, token_ptr points to the token
     413             :          * to send to the server (or GSS_C_NO_BUFFER on the first pass).
     414             :          * Every generated token is stored in send_tok which is then
     415             :          * transmitted to the server; every received token is stored in
     416             :          * recv_tok, which token_ptr is then set to, to be processed by
     417             :          * the next call to gss_init_sec_context.
     418             :          * 
     419             :          * GSS-API guarantees that send_tok's length will be non-zero
     420             :          * if and only if the server is expecting another token from us,
     421             :          * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
     422             :          * and only if the server has another token to send us.
     423             :          */
     424             : 
     425             :         /*
     426             :          * We always want to ask for the replay, and integ flags.
     427             :          * We may ask for delegation based on config in the tds.conf and other conf files.
     428             :          */
     429           0 :         gssapi_flags = GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG;
     430             : 
     431           0 :         if (tds->login->gssapi_use_delegation)
     432           0 :                 gssapi_flags |= GSS_C_DELEG_FLAG;
     433           0 :         if (tds->login->mutual_authentication || IS_TDS7_PLUS(tds->conn))
     434           0 :                 gssapi_flags |= GSS_C_MUTUAL_FLAG;
     435             : 
     436           0 :         cb = tds_gss_get_channel_binding(tds);
     437             : 
     438           0 :         maj_stat =
     439           0 :                 gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &auth->gss_context, auth->target_name, GSS_C_NULL_OID,
     440             :                                      gssapi_flags, 0, cb, token_ptr, &pmech, &send_tok, &ret_flags, NULL /* ignore time_rec */ );
     441             : 
     442           0 :         free(cb);
     443             : 
     444           0 :         tdsdump_log(TDS_DBG_NETWORK, "gss_init_sec_context: actual mechanism at %p\n", pmech);
     445           0 :         if (pmech && pmech->elements) {
     446           0 :                 tdsdump_dump_buf(TDS_DBG_NETWORK, "actual mechanism", pmech->elements, pmech->length);
     447             :         }
     448             :         
     449           0 :         auth->last_stat = maj_stat;
     450             :         
     451           0 :         switch (maj_stat) {
     452           0 :         case GSS_S_COMPLETE: 
     453           0 :                 msg = "GSS_S_COMPLETE: gss_init_sec_context completed successfully.";
     454           0 :                 break;
     455           0 :         case GSS_S_CONTINUE_NEEDED: 
     456           0 :                 msg = "GSS_S_CONTINUE_NEEDED: gss_init_sec_context() routine must be called again.";
     457           0 :                 break;
     458           0 :         case GSS_S_FAILURE: 
     459           0 :                 msg = "GSS_S_FAILURE: The routine failed for reasons that are not defined at the GSS level.";
     460           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_init_sec_context: min_stat %ld \"%s\"\n", 
     461             :                                                 (long) min_stat, error_message(min_stat));
     462             :                 break;
     463           0 :         case GSS_S_BAD_BINDINGS: 
     464           0 :                 msg = "GSS_S_BAD_BINDINGS: The channel bindings are not valid.";
     465           0 :                 break;
     466           0 :         case GSS_S_BAD_MECH: 
     467           0 :                 msg = "GSS_S_BAD_MECH: The request security mechanism is not supported.";
     468           0 :                 break;
     469           0 :         case GSS_S_BAD_NAME: 
     470           0 :                 msg = "GSS_S_BAD_NAME: The target_name parameter is not valid.";
     471           0 :                 break;
     472           0 :         case GSS_S_BAD_SIG: 
     473           0 :                 msg = "GSS_S_BAD_SIG: The input token contains an incorrect integrity check value.";
     474           0 :                 break;
     475           0 :         case GSS_S_CREDENTIALS_EXPIRED: 
     476           0 :                 msg = "GSS_S_CREDENTIALS_EXPIRED: The supplied credentials are no longer valid.";
     477           0 :                 break;
     478           0 :         case GSS_S_DEFECTIVE_CREDENTIAL: 
     479           0 :                 msg = "GSS_S_DEFECTIVE_CREDENTIAL: Consistency checks performed on the credential failed.";
     480           0 :                 break;
     481           0 :         case GSS_S_DEFECTIVE_TOKEN: 
     482           0 :                 msg = "GSS_S_DEFECTIVE_TOKEN: Consistency checks performed on the input token failed.";
     483           0 :                 break;
     484           0 :         case GSS_S_DUPLICATE_TOKEN: 
     485           0 :                 msg = "GSS_S_DUPLICATE_TOKEN: The token is a duplicate of a token that has already been processed.";
     486           0 :                 break;
     487           0 :         case GSS_S_NO_CONTEXT: 
     488           0 :                 msg = "GSS_S_NO_CONTEXT: The context handle provided by the caller does not refer to a valid security context.";
     489           0 :                 break;
     490           0 :         case GSS_S_NO_CRED: 
     491           0 :                 msg = "GSS_S_NO_CRED: The supplied credential handle does not refer to a valid credential, the supplied credential is not";
     492           0 :                 break;
     493           0 :         case GSS_S_OLD_TOKEN: 
     494           0 :                 msg = "GSS_S_OLD_TOKEN: The token is too old to be checked for duplication against previous tokens which have already been processed.";
     495           0 :                 break;
     496             :         }
     497             :         
     498           0 :         if (GSS_ERROR(maj_stat)) {
     499           0 :                 gss_release_buffer(&min_stat, &send_tok);
     500           0 :                 tdsdump_log(TDS_DBG_NETWORK, "gss_init_sec_context: %s\n", msg);
     501             :                 return TDS_FAIL;
     502             :         }
     503             : 
     504           0 :         auth->tds_auth.packet = (uint8_t *) send_tok.value;
     505           0 :         auth->tds_auth.packet_len = (int) send_tok.length;
     506             : 
     507           0 :         return TDS_SUCCESS;
     508             : }
     509             : 
     510             : static void
     511           0 : tds5_send_msg(TDSSOCKET *tds, uint16_t msg_type)
     512             : {
     513           0 :         tds_put_tinyint(tds, TDS_MSG_TOKEN);
     514           0 :         tds_put_tinyint(tds, 3); /* length */
     515           0 :         tds_put_tinyint(tds, 1); /* status, 1=has params */
     516           0 :         tds_put_smallint(tds, msg_type);
     517           0 : }
     518             : 
     519             : TDSRET
     520           0 : tds5_gss_send(TDSSOCKET *tds)
     521             : {
     522           0 :         uint32_t flags = TDS5_SEC_NETWORK_AUTHENTICATION;
     523             : 
     524           0 :         if (!tds->conn->authentication)
     525             :                 return TDS_FAIL;
     526             : 
     527           0 :         if (tds->login) {
     528           0 :                 if (tds->login->gssapi_use_delegation)
     529           0 :                         flags |= TDS5_SEC_DELEGATION;
     530           0 :                 if (tds->login->mutual_authentication)
     531           0 :                         flags |= TDS5_SEC_MUTUAL_AUTHENTICATION;
     532             :         }
     533             : 
     534           0 :         tds5_send_msg(tds, TDS5_MSG_SEC_OPAQUE);
     535             : 
     536           0 :         tds_put_byte(tds, TDS5_PARAMFMT_TOKEN);
     537           0 :         TDS_START_LEN_USMALLINT(tds) {
     538           0 :                 tds_put_smallint(tds, 5); /* # parameters */
     539             : 
     540           0 :                 tds_put_n(tds, NULL, 6); /* name len + output + usertype */
     541           0 :                 tds_put_tinyint(tds, SYBINTN);
     542           0 :                 tds_put_tinyint(tds, 4);
     543           0 :                 tds_put_tinyint(tds, 0); /* locale len */
     544             : 
     545           0 :                 tds_put_n(tds, NULL, 6); /* name len + output + usertype */
     546           0 :                 tds_put_tinyint(tds, SYBINTN);
     547           0 :                 tds_put_tinyint(tds, 4);
     548           0 :                 tds_put_tinyint(tds, 0); /* locale len */
     549             : 
     550           0 :                 tds_put_n(tds, NULL, 6); /* name len + output + usertype */
     551           0 :                 tds_put_tinyint(tds, SYBVARBINARY);
     552           0 :                 tds_put_tinyint(tds, 255);
     553           0 :                 tds_put_tinyint(tds, 0); /* locale len */
     554             : 
     555           0 :                 tds_put_n(tds, NULL, 6); /* name len + output + usertype */
     556           0 :                 tds_put_tinyint(tds, SYBLONGBINARY);
     557           0 :                 tds_put_int(tds, 0x7fffffff);
     558           0 :                 tds_put_tinyint(tds, 0); /* locale len */
     559             : 
     560           0 :                 tds_put_n(tds, NULL, 6); /* name len + output + usertype */
     561           0 :                 tds_put_tinyint(tds, SYBINTN);
     562           0 :                 tds_put_tinyint(tds, 4);
     563           0 :                 tds_put_tinyint(tds, 0); /* locale len */
     564           0 :         } TDS_END_LEN
     565             : 
     566           0 :         tds_put_byte(tds, TDS5_PARAMS_TOKEN);
     567             : 
     568           0 :         tds_put_tinyint(tds, 4);
     569           0 :         tds_put_int(tds, TDS5_SEC_VERSION);
     570             : 
     571           0 :         tds_put_tinyint(tds, 4);
     572           0 :         tds_put_int(tds, TDS5_SEC_SECSESS);
     573             : 
     574           0 :         tds_put_tinyint(tds, 12);
     575           0 :         tds_put_n(tds, "\x06\x0a\x2b\x06\x01\x04\x01\x87\x01\x04\x06\x06", 12); /* KRB5 Sybase OID */
     576             : 
     577           0 :         tds_put_int(tds, tds->conn->authentication->packet_len);
     578           0 :         tds_put_n(tds, tds->conn->authentication->packet, tds->conn->authentication->packet_len);
     579             : 
     580           0 :         tds_put_tinyint(tds, 4);
     581           0 :         tds_put_int(tds, flags);
     582             : 
     583           0 :         return TDS_SUCCESS;
     584             : }
     585             : 
     586             : /** @} */
     587             : 
     588             : #endif

Generated by: LCOV version 1.13