LCOV - code coverage report
Current view: top level - auth/kerberos - gssapi_helper.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 165 197 83.8 %
Date: 2024-06-10 12:05:21 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    GSSAPI helper functions
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2008,2015
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/gssapi.h"
      23             : #include "auth/kerberos/pac_utils.h"
      24             : #include "auth/kerberos/gssapi_helper.h"
      25             : 
      26             : #undef DBGC_CLASS
      27             : #define DBGC_CLASS DBGC_AUTH
      28             : 
      29        8174 : size_t gssapi_get_sig_size(gss_ctx_id_t gssapi_context,
      30             :                            const gss_OID mech,
      31             :                            uint32_t gss_want_flags,
      32             :                            size_t data_size)
      33             : {
      34        8174 :         TALLOC_CTX *frame = talloc_stackframe();
      35        8174 :         size_t sig_size = 0;
      36             : 
      37        8174 :         if (gss_want_flags & GSS_C_CONF_FLAG) {
      38         184 :                 OM_uint32 min_stat, maj_stat;
      39        5455 :                 bool want_sealing = true;
      40        5455 :                 int sealed = 0;
      41         184 :                 gss_iov_buffer_desc iov[2];
      42             : 
      43        5455 :                 if (!(gss_want_flags & GSS_C_DCE_STYLE)) {
      44           0 :                         TALLOC_FREE(frame);
      45           0 :                         return 0;
      46             :                 }
      47             : 
      48             :                 /*
      49             :                  * gss_wrap_iov_length() only needs the type and length
      50             :                  */
      51        5455 :                 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
      52        5455 :                 iov[0].buffer.value = NULL;
      53        5455 :                 iov[0].buffer.length = 0;
      54        5455 :                 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
      55        5455 :                 iov[1].buffer.value = NULL;
      56        5455 :                 iov[1].buffer.length = data_size;
      57             : 
      58        5455 :                 maj_stat = gss_wrap_iov_length(&min_stat,
      59             :                                                gssapi_context,
      60             :                                                want_sealing,
      61             :                                                GSS_C_QOP_DEFAULT,
      62             :                                                &sealed,
      63             :                                                iov, ARRAY_SIZE(iov));
      64        5455 :                 if (maj_stat) {
      65           0 :                         DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
      66             :                                   gssapi_error_string(frame,
      67             :                                                       maj_stat,
      68             :                                                       min_stat,
      69             :                                                       mech)));
      70           0 :                         TALLOC_FREE(frame);
      71           0 :                         return 0;
      72             :                 }
      73             : 
      74        5455 :                 sig_size = iov[0].buffer.length;
      75        2719 :         } else if (gss_want_flags & GSS_C_INTEG_FLAG) {
      76           2 :                 NTSTATUS status;
      77           2 :                 uint32_t keytype;
      78             : 
      79        2719 :                 status = gssapi_get_session_key(frame,
      80             :                                                 gssapi_context,
      81             :                                                 NULL, &keytype);
      82        2719 :                 if (!NT_STATUS_IS_OK(status)) {
      83           0 :                         TALLOC_FREE(frame);
      84           0 :                         return 0;
      85             :                 }
      86             : 
      87        2719 :                 switch (keytype) {
      88          64 :                 case ENCTYPE_DES_CBC_MD5:
      89             :                 case ENCTYPE_DES_CBC_CRC:
      90             :                 case ENCTYPE_ARCFOUR_HMAC:
      91             :                 case ENCTYPE_ARCFOUR_HMAC_EXP:
      92          64 :                         sig_size = 37;
      93          64 :                         break;
      94        2655 :                 default:
      95        2655 :                         sig_size = 28;
      96        2655 :                         break;
      97             :                 }
      98             :         }
      99             : 
     100        8174 :         TALLOC_FREE(frame);
     101        7988 :         return sig_size;
     102             : }
     103             : 
     104      339221 : NTSTATUS gssapi_seal_packet(gss_ctx_id_t gssapi_context,
     105             :                             const gss_OID mech,
     106             :                             bool hdr_signing, size_t sig_size,
     107             :                             uint8_t *data, size_t length,
     108             :                             const uint8_t *whole_pdu, size_t pdu_length,
     109             :                             TALLOC_CTX *mem_ctx,
     110             :                             DATA_BLOB *sig)
     111             : {
     112        1319 :         OM_uint32 maj_stat, min_stat;
     113        1319 :         gss_iov_buffer_desc iov[4];
     114      339221 :         int req_seal = 1;
     115      339221 :         int sealed = 0;
     116      339221 :         const uint8_t *pre_sign_ptr = NULL;
     117      339221 :         size_t pre_sign_len = 0;
     118      339221 :         const uint8_t *post_sign_ptr = NULL;
     119      339221 :         size_t post_sign_len = 0;
     120             : 
     121      339221 :         if (hdr_signing) {
     122      333732 :                 const uint8_t *de = data + length;
     123      333732 :                 const uint8_t *we = whole_pdu + pdu_length;
     124             : 
     125      333732 :                 if (data < whole_pdu) {
     126           0 :                         return NT_STATUS_INVALID_PARAMETER;
     127             :                 }
     128             : 
     129      333732 :                 if (de > we) {
     130           0 :                         return NT_STATUS_INVALID_PARAMETER;
     131             :                 }
     132             : 
     133      333732 :                 pre_sign_len = data - whole_pdu;
     134      333732 :                 if (pre_sign_len > 0) {
     135      333732 :                         pre_sign_ptr = whole_pdu;
     136             :                 }
     137      333732 :                 post_sign_len = we - de;
     138      333732 :                 if (post_sign_len > 0) {
     139      333732 :                         post_sign_ptr = de;
     140             :                 }
     141             :         }
     142             : 
     143      339221 :         sig->length = sig_size;
     144      339221 :         if (sig->length == 0) {
     145           0 :                 return NT_STATUS_ACCESS_DENIED;
     146             :         }
     147             : 
     148      339221 :         sig->data = talloc_zero_array(mem_ctx, uint8_t, sig->length);
     149      339221 :         if (sig->data == NULL) {
     150           0 :                 return NT_STATUS_NO_MEMORY;
     151             :         }
     152             : 
     153      339221 :         iov[0].type          = GSS_IOV_BUFFER_TYPE_HEADER;
     154      339221 :         iov[0].buffer.length = sig->length;
     155      339221 :         iov[0].buffer.value  = sig->data;
     156             : 
     157      339221 :         if (pre_sign_ptr != NULL) {
     158      333732 :                 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
     159      333732 :                 iov[1].buffer.length = pre_sign_len;
     160      333732 :                 iov[1].buffer.value = discard_const(pre_sign_ptr);
     161             :         } else {
     162        5489 :                 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
     163        5489 :                 iov[1].buffer.length = 0;
     164        5489 :                 iov[1].buffer.value = NULL;
     165             :         }
     166             : 
     167             :         /* data is encrypted in place, which is ok */
     168      339221 :         iov[2].type          = GSS_IOV_BUFFER_TYPE_DATA;
     169      339221 :         iov[2].buffer.length = length;
     170      339221 :         iov[2].buffer.value  = data;
     171             : 
     172      339221 :         if (post_sign_ptr != NULL) {
     173      333732 :                 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
     174      333732 :                 iov[3].buffer.length = post_sign_len;
     175      333732 :                 iov[3].buffer.value = discard_const(post_sign_ptr);
     176             :         } else {
     177        5489 :                 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
     178        5489 :                 iov[3].buffer.length = 0;
     179        5489 :                 iov[3].buffer.value = NULL;
     180             :         }
     181             : 
     182      339221 :         maj_stat = gss_wrap_iov(&min_stat,
     183             :                                 gssapi_context,
     184             :                                 req_seal,
     185             :                                 GSS_C_QOP_DEFAULT,
     186             :                                 &sealed,
     187             :                                 iov, ARRAY_SIZE(iov));
     188      339221 :         if (GSS_ERROR(maj_stat)) {
     189           0 :                 char *error_string = gssapi_error_string(mem_ctx,
     190             :                                                          maj_stat,
     191             :                                                          min_stat,
     192             :                                                          mech);
     193           0 :                 DEBUG(1, ("gss_wrap_iov failed: %s\n", error_string));
     194           0 :                 talloc_free(error_string);
     195           0 :                 data_blob_free(sig);
     196           0 :                 return NT_STATUS_ACCESS_DENIED;
     197             :         }
     198             : 
     199      339221 :         if (req_seal == 1 && sealed == 0) {
     200           0 :                 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
     201           0 :                 data_blob_free(sig);
     202           0 :                 return NT_STATUS_ACCESS_DENIED;
     203             :         }
     204             : 
     205      339221 :         dump_data_pw("gssapi_seal_packet: sig\n", sig->data, sig->length);
     206      339221 :         dump_data_pw("gssapi_seal_packet: sealed\n", data, length);
     207             : 
     208      339221 :         DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
     209             :                    (int)iov[2].buffer.length, (int)iov[0].buffer.length));
     210             : 
     211      339221 :         return NT_STATUS_OK;
     212             : }
     213             : 
     214      339185 : NTSTATUS gssapi_unseal_packet(gss_ctx_id_t gssapi_context,
     215             :                               const gss_OID mech,
     216             :                               bool hdr_signing,
     217             :                               uint8_t *data, size_t length,
     218             :                               const uint8_t *whole_pdu, size_t pdu_length,
     219             :                               const DATA_BLOB *sig)
     220             : {
     221        1318 :         OM_uint32 maj_stat, min_stat;
     222        1318 :         gss_iov_buffer_desc iov[4];
     223        1318 :         gss_qop_t qop_state;
     224      339185 :         int sealed = 0;
     225      339185 :         const uint8_t *pre_sign_ptr = NULL;
     226      339185 :         size_t pre_sign_len = 0;
     227      339185 :         const uint8_t *post_sign_ptr = NULL;
     228      339185 :         size_t post_sign_len = 0;
     229             : 
     230      339185 :         if (hdr_signing) {
     231      333696 :                 const uint8_t *de = data + length;
     232      333696 :                 const uint8_t *we = whole_pdu + pdu_length;
     233             : 
     234      333696 :                 if (data < whole_pdu) {
     235           0 :                         return NT_STATUS_INVALID_PARAMETER;
     236             :                 }
     237             : 
     238      333696 :                 if (de > we) {
     239           0 :                         return NT_STATUS_INVALID_PARAMETER;
     240             :                 }
     241             : 
     242      333696 :                 pre_sign_len = data - whole_pdu;
     243      333696 :                 if (pre_sign_len > 0) {
     244      333696 :                         pre_sign_ptr = whole_pdu;
     245             :                 }
     246      333696 :                 post_sign_len = we - de;
     247      333696 :                 if (post_sign_len > 0) {
     248      333696 :                         post_sign_ptr = de;
     249             :                 }
     250             :         }
     251             : 
     252      339185 :         dump_data_pw("gssapi_unseal_packet: sig\n", sig->data, sig->length);
     253      339185 :         dump_data_pw("gssapi_unseal_packet: sealed\n", data, length);
     254             : 
     255      339185 :         iov[0].type          = GSS_IOV_BUFFER_TYPE_HEADER;
     256      339185 :         iov[0].buffer.length = sig->length;
     257      339185 :         iov[0].buffer.value  = sig->data;
     258             : 
     259      339185 :         if (pre_sign_ptr != NULL) {
     260      333696 :                 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
     261      333696 :                 iov[1].buffer.length = pre_sign_len;
     262      333696 :                 iov[1].buffer.value = discard_const(pre_sign_ptr);
     263             :         } else {
     264        5489 :                 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
     265        5489 :                 iov[1].buffer.length = 0;
     266        5489 :                 iov[1].buffer.value = NULL;
     267             :         }
     268             : 
     269             :         /* data is encrypted in place, which is ok */
     270      339185 :         iov[2].type          = GSS_IOV_BUFFER_TYPE_DATA;
     271      339185 :         iov[2].buffer.length = length;
     272      339185 :         iov[2].buffer.value  = data;
     273             : 
     274      339185 :         if (post_sign_ptr != NULL) {
     275      333696 :                 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
     276      333696 :                 iov[3].buffer.length = post_sign_len;
     277      333696 :                 iov[3].buffer.value = discard_const(post_sign_ptr);
     278             :         } else {
     279        5489 :                 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
     280        5489 :                 iov[3].buffer.length = 0;
     281        5489 :                 iov[3].buffer.value = NULL;
     282             :         }
     283             : 
     284      339185 :         maj_stat = gss_unwrap_iov(&min_stat,
     285             :                                   gssapi_context,
     286             :                                   &sealed,
     287             :                                   &qop_state,
     288             :                                   iov, ARRAY_SIZE(iov));
     289      339185 :         if (GSS_ERROR(maj_stat)) {
     290           0 :                 char *error_string = gssapi_error_string(NULL,
     291             :                                                          maj_stat,
     292             :                                                          min_stat,
     293             :                                                          mech);
     294           0 :                 DEBUG(1, ("gss_unwrap_iov failed: %s\n", error_string));
     295           0 :                 talloc_free(error_string);
     296             : 
     297           0 :                 return NT_STATUS_ACCESS_DENIED;
     298             :         }
     299             : 
     300      339185 :         if (sealed == 0) {
     301           0 :                 DEBUG(0, ("gss_unwrap_iov says data was not sealed!\n"));
     302           0 :                 return NT_STATUS_ACCESS_DENIED;
     303             :         }
     304             : 
     305      339185 :         DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
     306             :                    (int)iov[2].buffer.length, (int)iov[0].buffer.length));
     307             : 
     308      339185 :         return NT_STATUS_OK;
     309             : }
     310             : 
     311       66071 : NTSTATUS gssapi_sign_packet(gss_ctx_id_t gssapi_context,
     312             :                             const gss_OID mech,
     313             :                             bool hdr_signing,
     314             :                             const uint8_t *data, size_t length,
     315             :                             const uint8_t *whole_pdu, size_t pdu_length,
     316             :                             TALLOC_CTX *mem_ctx,
     317             :                             DATA_BLOB *sig)
     318             : {
     319         316 :         OM_uint32 maj_stat, min_stat;
     320         316 :         gss_buffer_desc input_token, output_token;
     321             : 
     322       66071 :         if (hdr_signing) {
     323       51398 :                 input_token.length = pdu_length;
     324       51398 :                 input_token.value = discard_const_p(uint8_t *, whole_pdu);
     325             :         } else {
     326       14673 :                 input_token.length = length;
     327       14673 :                 input_token.value = discard_const_p(uint8_t *, data);
     328             :         }
     329             : 
     330       66071 :         maj_stat = gss_get_mic(&min_stat,
     331             :                                gssapi_context,
     332             :                                GSS_C_QOP_DEFAULT,
     333             :                                &input_token,
     334             :                                &output_token);
     335       66071 :         if (GSS_ERROR(maj_stat)) {
     336           0 :                 char *error_string = gssapi_error_string(mem_ctx,
     337             :                                                          maj_stat,
     338             :                                                          min_stat,
     339             :                                                          mech);
     340           0 :                 DEBUG(1, ("GSS GetMic failed: %s\n", error_string));
     341           0 :                 talloc_free(error_string);
     342           0 :                 return NT_STATUS_ACCESS_DENIED;
     343             :         }
     344             : 
     345       66071 :         *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, output_token.length);
     346       66071 :         gss_release_buffer(&min_stat, &output_token);
     347       66071 :         if (sig->data == NULL) {
     348           0 :                 return NT_STATUS_NO_MEMORY;
     349             :         }
     350             : 
     351       66071 :         dump_data_pw("gssapi_sign_packet: sig\n", sig->data, sig->length);
     352             : 
     353       66071 :         return NT_STATUS_OK;
     354             : }
     355             : 
     356       65935 : NTSTATUS gssapi_check_packet(gss_ctx_id_t gssapi_context,
     357             :                              const gss_OID mech,
     358             :                              bool hdr_signing,
     359             :                              const uint8_t *data, size_t length,
     360             :                              const uint8_t *whole_pdu, size_t pdu_length,
     361             :                              const DATA_BLOB *sig)
     362             : {
     363         316 :         OM_uint32 maj_stat, min_stat;
     364         316 :         gss_buffer_desc input_token;
     365         316 :         gss_buffer_desc input_message;
     366         316 :         gss_qop_t qop_state;
     367             : 
     368       65935 :         dump_data_pw("gssapi_check_packet: sig\n", sig->data, sig->length);
     369             : 
     370       65935 :         if (hdr_signing) {
     371       51404 :                 input_message.length = pdu_length;
     372       51404 :                 input_message.value = discard_const(whole_pdu);
     373             :         } else {
     374       14531 :                 input_message.length = length;
     375       14531 :                 input_message.value = discard_const(data);
     376             :         }
     377             : 
     378       65935 :         input_token.length = sig->length;
     379       65935 :         input_token.value = sig->data;
     380             : 
     381       65935 :         maj_stat = gss_verify_mic(&min_stat,
     382             :                                   gssapi_context,
     383             :                                   &input_message,
     384             :                                   &input_token,
     385             :                                   &qop_state);
     386       65935 :         if (GSS_ERROR(maj_stat)) {
     387          14 :                 char *error_string = gssapi_error_string(NULL,
     388             :                                                          maj_stat,
     389             :                                                          min_stat,
     390             :                                                          mech);
     391          14 :                 DEBUG(1, ("GSS VerifyMic failed: %s\n", error_string));
     392          14 :                 talloc_free(error_string);
     393             : 
     394          14 :                 return NT_STATUS_ACCESS_DENIED;
     395             :         }
     396             : 
     397       65921 :         return NT_STATUS_OK;
     398             : }

Generated by: LCOV version 1.14