LCOV - code coverage report
Current view: top level - auth/gensec - schannel.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 421 544 77.4 %
Date: 2024-06-10 12:05:21 Functions: 21 21 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    dcerpc schannel operations
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include <tevent.h>
      25             : #include "lib/util/tevent_ntstatus.h"
      26             : #include "librpc/gen_ndr/ndr_schannel.h"
      27             : #include "auth/auth.h"
      28             : #include "auth/credentials/credentials.h"
      29             : #include "auth/gensec/gensec.h"
      30             : #include "auth/gensec/gensec_internal.h"
      31             : #include "auth/gensec/gensec_proto.h"
      32             : #include "../libcli/auth/schannel.h"
      33             : #include "librpc/gen_ndr/dcerpc.h"
      34             : #include "param/param.h"
      35             : #include "auth/gensec/gensec_toplevel_proto.h"
      36             : #include "libds/common/roles.h"
      37             : 
      38             : #include "lib/crypto/gnutls_helpers.h"
      39             : #include <gnutls/gnutls.h>
      40             : #include <gnutls/crypto.h>
      41             : 
      42             : #undef DBGC_CLASS
      43             : #define DBGC_CLASS DBGC_AUTH
      44             : 
      45             : struct schannel_state {
      46             :         struct gensec_security *gensec;
      47             :         uint64_t seq_num;
      48             :         bool initiator;
      49             :         struct netlogon_creds_CredentialState *creds;
      50             :         struct auth_user_info_dc *user_info_dc;
      51             : };
      52             : 
      53             : #define SETUP_SEQNUM(state, buf, initiator) do { \
      54             :         uint8_t *_buf = buf; \
      55             :         uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \
      56             :         uint32_t _seq_num_high = (state)->seq_num >> 32; \
      57             :         if (initiator) { \
      58             :                 _seq_num_high |= 0x80000000; \
      59             :         } \
      60             :         RSIVAL(_buf, 0, _seq_num_low); \
      61             :         RSIVAL(_buf, 4, _seq_num_high); \
      62             : } while(0)
      63             : 
      64        5012 : static struct schannel_state *netsec_create_state(
      65             :                                 struct gensec_security *gensec,
      66             :                                 struct netlogon_creds_CredentialState *creds,
      67             :                                 bool initiator)
      68             : {
      69         640 :         struct schannel_state *state;
      70             : 
      71        5012 :         state = talloc_zero(gensec, struct schannel_state);
      72        5012 :         if (state == NULL) {
      73           0 :                 return NULL;
      74             :         }
      75             : 
      76        5012 :         state->gensec = gensec;
      77        5012 :         state->initiator = initiator;
      78        5012 :         state->creds = netlogon_creds_copy(state, creds);
      79        5012 :         if (state->creds == NULL) {
      80           0 :                 talloc_free(state);
      81           0 :                 return NULL;
      82             :         }
      83             : 
      84        5012 :         gensec->private_data = state;
      85             : 
      86        5012 :         return state;
      87             : }
      88             : 
      89      147409 : static void netsec_offset_and_sizes(struct schannel_state *state,
      90             :                                     bool do_seal,
      91             :                                     uint32_t *_min_sig_size,
      92             :                                     uint32_t *_used_sig_size,
      93             :                                     uint32_t *_checksum_length,
      94             :                                     uint32_t *_confounder_ofs)
      95             : {
      96       16044 :         uint32_t min_sig_size;
      97       16044 :         uint32_t used_sig_size;
      98       16044 :         uint32_t checksum_length;
      99       16044 :         uint32_t confounder_ofs;
     100             : 
     101      147409 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     102       69409 :                 min_sig_size = 48;
     103       69409 :                 used_sig_size = 56;
     104             :                 /*
     105             :                  * Note: windows has a bug here and uses the old values...
     106             :                  *
     107             :                  * checksum_length = 32;
     108             :                  * confounder_ofs = 48;
     109             :                  */
     110       69409 :                 checksum_length = 8;
     111       69409 :                 confounder_ofs = 24;
     112             :         } else {
     113       67260 :                 min_sig_size = 24;
     114       67260 :                 used_sig_size = 32;
     115       67260 :                 checksum_length = 8;
     116       67260 :                 confounder_ofs = 24;
     117             :         }
     118             : 
     119      136713 :         if (do_seal) {
     120      110917 :                 min_sig_size += 8;
     121             :         }
     122             : 
     123      147409 :         if (_min_sig_size) {
     124       98252 :                 *_min_sig_size = min_sig_size;
     125             :         }
     126             : 
     127      147409 :         if (_used_sig_size) {
     128       98314 :                 *_used_sig_size = used_sig_size;
     129             :         }
     130             : 
     131      147409 :         if (_checksum_length) {
     132       98252 :                 *_checksum_length = checksum_length;
     133             :         }
     134             : 
     135      147409 :         if (_confounder_ofs) {
     136       98252 :                 *_confounder_ofs = confounder_ofs;
     137             :         }
     138      131365 : }
     139             : 
     140             : /*******************************************************************
     141             :  Encode or Decode the sequence number (which is symmetric)
     142             :  ********************************************************************/
     143       98252 : static NTSTATUS netsec_do_seq_num(struct schannel_state *state,
     144             :                                   const uint8_t *checksum,
     145             :                                   uint32_t checksum_length,
     146             :                                   uint8_t seq_num[8])
     147             : {
     148       98252 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     149       53426 :                 gnutls_cipher_hd_t cipher_hnd = NULL;
     150       53426 :                 gnutls_datum_t key = {
     151       53426 :                         .data = state->creds->session_key,
     152             :                         .size = sizeof(state->creds->session_key),
     153             :                 };
     154        7160 :                 uint32_t iv_size =
     155       53426 :                         gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
     156       53426 :                 uint8_t _iv[iv_size];
     157       53426 :                 gnutls_datum_t iv = {
     158             :                         .data = _iv,
     159             :                         .size = iv_size,
     160             :                 };
     161        7160 :                 int rc;
     162             : 
     163       53426 :                 ZERO_ARRAY(_iv);
     164             : 
     165       53426 :                 memcpy(iv.data + 0, checksum, 8);
     166       53426 :                 memcpy(iv.data + 8, checksum, 8);
     167             : 
     168       53426 :                 rc = gnutls_cipher_init(&cipher_hnd,
     169             :                                         GNUTLS_CIPHER_AES_128_CFB8,
     170             :                                         &key,
     171             :                                         &iv);
     172       53426 :                 if (rc < 0) {
     173           0 :                         return gnutls_error_to_ntstatus(rc,
     174             :                                                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
     175             :                 }
     176             : 
     177       53426 :                 rc = gnutls_cipher_encrypt(cipher_hnd, seq_num, 8);
     178       53426 :                 gnutls_cipher_deinit(cipher_hnd);
     179       53426 :                 if (rc < 0) {
     180           0 :                         return gnutls_error_to_ntstatus(rc,
     181             :                                                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
     182             :                 }
     183             : 
     184             :         } else {
     185        3536 :                 static const uint8_t zeros[4];
     186        3536 :                 uint8_t _sequence_key[16];
     187        3536 :                 gnutls_cipher_hd_t cipher_hnd;
     188       44826 :                 gnutls_datum_t sequence_key = {
     189             :                         .data = _sequence_key,
     190             :                         .size = sizeof(_sequence_key),
     191             :                 };
     192        3536 :                 uint8_t digest1[16];
     193        3536 :                 int rc;
     194             : 
     195       48362 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     196       44826 :                                       state->creds->session_key,
     197             :                                       sizeof(state->creds->session_key),
     198             :                                       zeros,
     199             :                                       sizeof(zeros),
     200             :                                       digest1);
     201       44826 :                 if (rc < 0) {
     202           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     203             :                 }
     204             : 
     205       44826 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     206             :                                       digest1,
     207             :                                       sizeof(digest1),
     208             :                                       checksum,
     209             :                                       checksum_length,
     210             :                                       _sequence_key);
     211       44826 :                 ZERO_ARRAY(digest1);
     212       44826 :                 if (rc < 0) {
     213           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     214             :                 }
     215             : 
     216       44826 :                 rc = gnutls_cipher_init(&cipher_hnd,
     217             :                                         GNUTLS_CIPHER_ARCFOUR_128,
     218             :                                         &sequence_key,
     219             :                                         NULL);
     220       44826 :                 if (rc < 0) {
     221           0 :                         ZERO_ARRAY(_sequence_key);
     222           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     223             :                 }
     224             : 
     225       44826 :                 rc = gnutls_cipher_encrypt(cipher_hnd,
     226             :                                            seq_num,
     227             :                                            8);
     228       44826 :                 gnutls_cipher_deinit(cipher_hnd);
     229       44826 :                 ZERO_ARRAY(_sequence_key);
     230       44826 :                 if (rc < 0) {
     231           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     232             :                 }
     233             :         }
     234             : 
     235       98252 :         state->seq_num++;
     236             : 
     237       98252 :         return NT_STATUS_OK;
     238             : }
     239             : 
     240       69968 : static NTSTATUS netsec_do_seal(struct schannel_state *state,
     241             :                                const uint8_t seq_num[8],
     242             :                                uint8_t confounder[8],
     243             :                                uint8_t *data, uint32_t length,
     244             :                                bool forward)
     245             : {
     246       69968 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     247       34220 :                 gnutls_cipher_hd_t cipher_hnd = NULL;
     248       34220 :                 uint8_t sess_kf0[16] = {0};
     249       34220 :                 gnutls_datum_t key = {
     250             :                         .data = sess_kf0,
     251             :                         .size = sizeof(sess_kf0),
     252             :                 };
     253        3756 :                 uint32_t iv_size =
     254       34220 :                         gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
     255       34220 :                 uint8_t _iv[iv_size];
     256       34220 :                 gnutls_datum_t iv = {
     257             :                         .data = _iv,
     258             :                         .size = iv_size,
     259             :                 };
     260        3756 :                 uint32_t i;
     261        3756 :                 int rc;
     262             : 
     263      581740 :                 for (i = 0; i < key.size; i++) {
     264      547520 :                         key.data[i] = state->creds->session_key[i] ^ 0xf0;
     265             :                 }
     266             : 
     267       34220 :                 ZERO_ARRAY(_iv);
     268             : 
     269       34220 :                 memcpy(iv.data + 0, seq_num, 8);
     270       34220 :                 memcpy(iv.data + 8, seq_num, 8);
     271             : 
     272       34220 :                 rc = gnutls_cipher_init(&cipher_hnd,
     273             :                                         GNUTLS_CIPHER_AES_128_CFB8,
     274             :                                         &key,
     275             :                                         &iv);
     276       34220 :                 if (rc < 0) {
     277           0 :                         DBG_ERR("ERROR: gnutls_cipher_init: %s\n",
     278             :                                 gnutls_strerror(rc));
     279           0 :                         return NT_STATUS_NO_MEMORY;
     280             :                 }
     281             : 
     282       34220 :                 if (forward) {
     283       17108 :                         rc = gnutls_cipher_encrypt(cipher_hnd,
     284             :                                                    confounder,
     285             :                                                    8);
     286       17108 :                         if (rc < 0) {
     287           0 :                                 gnutls_cipher_deinit(cipher_hnd);
     288           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     289             :                         }
     290             : 
     291       17108 :                         rc = gnutls_cipher_encrypt(cipher_hnd,
     292             :                                                    data,
     293             :                                                    length);
     294       17108 :                         if (rc < 0) {
     295           0 :                                 gnutls_cipher_deinit(cipher_hnd);
     296           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     297             :                         }
     298             :                 } else {
     299             : 
     300             :                         /*
     301             :                          * Workaround bug present in gnutls 3.6.8:
     302             :                          *
     303             :                          * gnutls_cipher_decrypt() uses an optimization
     304             :                          * internally that breaks decryption when processing
     305             :                          * buffers with their length not being a multiple
     306             :                          * of the blocksize.
     307             :                          */
     308             : 
     309       17112 :                         uint8_t tmp[16] = { 0, };
     310       17112 :                         uint32_t tmp_dlength = MIN(length, sizeof(tmp) - 8);
     311             : 
     312       17112 :                         memcpy(tmp, confounder, 8);
     313       17112 :                         memcpy(tmp + 8, data, tmp_dlength);
     314             : 
     315       18990 :                         rc = gnutls_cipher_decrypt(cipher_hnd,
     316             :                                                    tmp,
     317       17112 :                                                    8 + tmp_dlength);
     318       17112 :                         if (rc < 0) {
     319           0 :                                 ZERO_STRUCT(tmp);
     320           0 :                                 gnutls_cipher_deinit(cipher_hnd);
     321           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     322             :                         }
     323             : 
     324       17112 :                         memcpy(confounder, tmp, 8);
     325       17112 :                         memcpy(data, tmp + 8, tmp_dlength);
     326       17112 :                         ZERO_STRUCT(tmp);
     327             : 
     328       17112 :                         if (length > tmp_dlength) {
     329       18980 :                                 rc = gnutls_cipher_decrypt(cipher_hnd,
     330       17107 :                                                            data + tmp_dlength,
     331       17107 :                                                            length - tmp_dlength);
     332       17107 :                                 if (rc < 0) {
     333           0 :                                         gnutls_cipher_deinit(cipher_hnd);
     334           0 :                                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     335             :                                 }
     336             :                         }
     337             :                 }
     338       34220 :                 gnutls_cipher_deinit(cipher_hnd);
     339             :         } else {
     340        1924 :                 gnutls_cipher_hd_t cipher_hnd;
     341        1924 :                 uint8_t _sealing_key[16];
     342       35748 :                 gnutls_datum_t sealing_key = {
     343             :                         .data = _sealing_key,
     344             :                         .size = sizeof(_sealing_key),
     345             :                 };
     346        1924 :                 static const uint8_t zeros[4];
     347        1924 :                 uint8_t digest2[16];
     348        1924 :                 uint8_t sess_kf0[16];
     349        1924 :                 int rc;
     350        1924 :                 int i;
     351             : 
     352      607716 :                 for (i = 0; i < 16; i++) {
     353      571968 :                         sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
     354             :                 }
     355             : 
     356       35748 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     357             :                                       sess_kf0,
     358             :                                       sizeof(sess_kf0),
     359             :                                       zeros,
     360             :                                       4,
     361             :                                       digest2);
     362       35748 :                 if (rc < 0) {
     363           0 :                         ZERO_ARRAY(digest2);
     364           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     365             :                 }
     366             : 
     367       35748 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     368             :                                       digest2,
     369             :                                       sizeof(digest2),
     370             :                                       seq_num,
     371             :                                       8,
     372             :                                       _sealing_key);
     373             : 
     374       35748 :                 ZERO_ARRAY(digest2);
     375       35748 :                 if (rc < 0) {
     376           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     377             :                 }
     378             : 
     379       35748 :                 rc = gnutls_cipher_init(&cipher_hnd,
     380             :                                         GNUTLS_CIPHER_ARCFOUR_128,
     381             :                                         &sealing_key,
     382             :                                         NULL);
     383       35748 :                 if (rc < 0) {
     384           0 :                         ZERO_ARRAY(_sealing_key);
     385           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     386             :                 }
     387       35748 :                 rc = gnutls_cipher_encrypt(cipher_hnd,
     388             :                                            confounder,
     389             :                                            8);
     390       35748 :                 if (rc < 0) {
     391           0 :                         ZERO_ARRAY(_sealing_key);
     392           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     393             :                 }
     394       35748 :                 gnutls_cipher_deinit(cipher_hnd);
     395       35748 :                 rc = gnutls_cipher_init(&cipher_hnd,
     396             :                                         GNUTLS_CIPHER_ARCFOUR_128,
     397             :                                         &sealing_key,
     398             :                                         NULL);
     399       35748 :                 if (rc < 0) {
     400           0 :                         ZERO_ARRAY(_sealing_key);
     401           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     402             :                 }
     403       35748 :                 rc = gnutls_cipher_encrypt(cipher_hnd,
     404             :                                            data,
     405             :                                            length);
     406       35748 :                 gnutls_cipher_deinit(cipher_hnd);
     407       35748 :                 ZERO_ARRAY(_sealing_key);
     408       35748 :                 if (rc < 0) {
     409           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     410             :                 }
     411             :         }
     412             : 
     413       69968 :         return NT_STATUS_OK;
     414             : }
     415             : 
     416             : /*******************************************************************
     417             :  Create a digest over the entire packet (including the data), and
     418             :  MD5 it with the session key.
     419             :  ********************************************************************/
     420       98252 : static NTSTATUS netsec_do_sign(struct schannel_state *state,
     421             :                                const uint8_t *confounder,
     422             :                                const uint8_t *data, size_t length,
     423             :                                uint8_t header[8],
     424             :                                uint8_t *checksum)
     425             : {
     426       98252 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     427       53426 :                 gnutls_hmac_hd_t hmac_hnd = NULL;
     428        7160 :                 int rc;
     429             : 
     430       60586 :                 rc = gnutls_hmac_init(&hmac_hnd,
     431             :                                       GNUTLS_MAC_SHA256,
     432       53426 :                                       state->creds->session_key,
     433             :                                       sizeof(state->creds->session_key));
     434       53426 :                 if (rc < 0) {
     435           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     436             :                 }
     437             : 
     438       53426 :                 if (confounder) {
     439       34200 :                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
     440       34200 :                         SSVAL(header, 2, NL_SEAL_AES128);
     441       34200 :                         SSVAL(header, 4, 0xFFFF);
     442       34200 :                         SSVAL(header, 6, 0x0000);
     443             : 
     444       34200 :                         rc = gnutls_hmac(hmac_hnd, header, 8);
     445       34200 :                         if (rc < 0) {
     446           0 :                                 gnutls_hmac_deinit(hmac_hnd, NULL);
     447           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     448             :                         }
     449       34200 :                         rc = gnutls_hmac(hmac_hnd, confounder, 8);
     450       34200 :                         if (rc < 0) {
     451           0 :                                 gnutls_hmac_deinit(hmac_hnd, NULL);
     452           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     453             :                         }
     454             :                 } else {
     455       19226 :                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
     456       19226 :                         SSVAL(header, 2, NL_SEAL_NONE);
     457       19226 :                         SSVAL(header, 4, 0xFFFF);
     458       19226 :                         SSVAL(header, 6, 0x0000);
     459             : 
     460       19226 :                         rc = gnutls_hmac(hmac_hnd, header, 8);
     461       19226 :                         if (rc < 0) {
     462           0 :                                 gnutls_hmac_deinit(hmac_hnd, NULL);
     463           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     464             :                         }
     465             :                 }
     466             : 
     467       53426 :                 rc = gnutls_hmac(hmac_hnd, data, length);
     468       53426 :                 if (rc < 0) {
     469           0 :                         gnutls_hmac_deinit(hmac_hnd, NULL);
     470           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     471             :                 }
     472             : 
     473       53426 :                 gnutls_hmac_deinit(hmac_hnd, checksum);
     474             :         } else {
     475        3536 :                 uint8_t packet_digest[16];
     476        3536 :                 static const uint8_t zeros[4];
     477       44826 :                 gnutls_hash_hd_t hash_hnd = NULL;
     478        3536 :                 int rc;
     479             : 
     480       44826 :                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
     481       44826 :                 if (rc < 0) {
     482           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     483             :                 }
     484             : 
     485       44826 :                 rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
     486       44826 :                 if (rc < 0) {
     487           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
     488           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     489             :                 }
     490       44826 :                 if (confounder) {
     491       35728 :                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
     492       35728 :                         SSVAL(header, 2, NL_SEAL_RC4);
     493       35728 :                         SSVAL(header, 4, 0xFFFF);
     494       35728 :                         SSVAL(header, 6, 0x0000);
     495             : 
     496       35728 :                         rc = gnutls_hash(hash_hnd, header, 8);
     497       35728 :                         if (rc < 0) {
     498           0 :                                 gnutls_hash_deinit(hash_hnd, NULL);
     499           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     500             :                         }
     501       35728 :                         rc = gnutls_hash(hash_hnd, confounder, 8);
     502       35728 :                         if (rc < 0) {
     503           0 :                                 gnutls_hash_deinit(hash_hnd, NULL);
     504           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     505             :                         }
     506             :                 } else {
     507        9098 :                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
     508        9098 :                         SSVAL(header, 2, NL_SEAL_NONE);
     509        9098 :                         SSVAL(header, 4, 0xFFFF);
     510        9098 :                         SSVAL(header, 6, 0x0000);
     511             : 
     512        9098 :                         rc = gnutls_hash(hash_hnd, header, 8);
     513        9098 :                         if (rc < 0) {
     514           0 :                                 gnutls_hash_deinit(hash_hnd, NULL);
     515           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     516             :                         }
     517             :                 }
     518       44826 :                 rc = gnutls_hash(hash_hnd, data, length);
     519       44826 :                 if (rc < 0) {
     520           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
     521           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
     522             :                 }
     523       44826 :                 gnutls_hash_deinit(hash_hnd, packet_digest);
     524             : 
     525       48362 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     526       44826 :                                       state->creds->session_key,
     527             :                                       sizeof(state->creds->session_key),
     528             :                                       packet_digest,
     529             :                                       sizeof(packet_digest),
     530             :                                       checksum);
     531       44826 :                 ZERO_ARRAY(packet_digest);
     532       44826 :                 if (rc < 0) {
     533           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     534             :                 }
     535             :         }
     536             : 
     537       98252 :         return NT_STATUS_OK;
     538             : }
     539             : 
     540       49095 : static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
     541             :                                 bool do_unseal,
     542             :                                 uint8_t *data, size_t length,
     543             :                                 const uint8_t *whole_pdu, size_t pdu_length,
     544             :                                 const DATA_BLOB *sig)
     545             : {
     546       49095 :         uint32_t min_sig_size = 0;
     547        5348 :         uint8_t header[8];
     548        5348 :         uint8_t checksum[32];
     549       49095 :         uint32_t checksum_length = sizeof(checksum_length);
     550        5348 :         uint8_t _confounder[8];
     551       49095 :         uint8_t *confounder = NULL;
     552       49095 :         uint32_t confounder_ofs = 0;
     553        5348 :         uint8_t seq_num[8];
     554        5348 :         bool ret;
     555       49095 :         const uint8_t *sign_data = NULL;
     556       49095 :         size_t sign_length = 0;
     557        5348 :         NTSTATUS status;
     558             : 
     559       49095 :         netsec_offset_and_sizes(state,
     560             :                                 do_unseal,
     561             :                                 &min_sig_size,
     562             :                                 NULL,
     563             :                                 &checksum_length,
     564             :                                 &confounder_ofs);
     565             : 
     566       49095 :         if (sig->length < min_sig_size) {
     567           0 :                 return NT_STATUS_ACCESS_DENIED;
     568             :         }
     569             : 
     570       49095 :         if (do_unseal) {
     571       34954 :                 confounder = _confounder;
     572       34954 :                 memcpy(confounder, sig->data+confounder_ofs, 8);
     573             :         } else {
     574       11613 :                 confounder = NULL;
     575             :         }
     576             : 
     577       49095 :         SETUP_SEQNUM(state, seq_num, !state->initiator);
     578             : 
     579       49095 :         if (do_unseal) {
     580       34954 :                 status = netsec_do_seal(state,
     581             :                                         seq_num,
     582             :                                         confounder,
     583             :                                         data,
     584             :                                         length,
     585             :                                         false);
     586       34954 :                 if (!NT_STATUS_IS_OK(status)) {
     587           0 :                         DBG_WARNING("netsec_do_seal failed: %s\n", nt_errstr(status));
     588           0 :                         return NT_STATUS_ACCESS_DENIED;
     589             :                 }
     590             :         }
     591             : 
     592       49095 :         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     593       43537 :                 sign_data = whole_pdu;
     594       43537 :                 sign_length = pdu_length;
     595             :         } else {
     596         210 :                 sign_data = data;
     597         210 :                 sign_length = length;
     598             :         }
     599             : 
     600       49095 :         status = netsec_do_sign(state,
     601             :                                 confounder,
     602             :                                 sign_data,
     603             :                                 sign_length,
     604             :                                 header,
     605             :                                 checksum);
     606       49095 :         if (!NT_STATUS_IS_OK(status)) {
     607           0 :                 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
     608           0 :                 return NT_STATUS_ACCESS_DENIED;
     609             :         }
     610             : 
     611       49095 :         ret = mem_equal_const_time(checksum, sig->data+16, checksum_length);
     612       49095 :         if (!ret) {
     613           0 :                 dump_data_pw("calc digest:", checksum, checksum_length);
     614           0 :                 dump_data_pw("wire digest:", sig->data+16, checksum_length);
     615           0 :                 return NT_STATUS_ACCESS_DENIED;
     616             :         }
     617             : 
     618       49095 :         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
     619       49095 :         if (!NT_STATUS_IS_OK(status)) {
     620           0 :                 DBG_WARNING("netsec_do_seq_num failed: %s\n",
     621             :                             nt_errstr(status));
     622           0 :                 return status;
     623             :         }
     624             : 
     625       49095 :         ZERO_ARRAY(checksum);
     626             : 
     627       49095 :         ret = mem_equal_const_time(seq_num, sig->data+8, 8);
     628       49095 :         if (!ret) {
     629           0 :                 dump_data_pw("calc seq num:", seq_num, 8);
     630           0 :                 dump_data_pw("wire seq num:", sig->data+8, 8);
     631           0 :                 return NT_STATUS_ACCESS_DENIED;
     632             :         }
     633             : 
     634       49095 :         return NT_STATUS_OK;
     635             : }
     636             : 
     637       49157 : static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
     638             : {
     639       49157 :         uint32_t sig_size = 0;
     640             : 
     641       54505 :         netsec_offset_and_sizes(state,
     642             :                                 true,
     643             :                                 NULL,
     644             :                                 &sig_size,
     645             :                                 NULL,
     646             :                                 NULL);
     647             : 
     648       49157 :         return sig_size;
     649             : }
     650             : 
     651       49157 : static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
     652             :                                 TALLOC_CTX *mem_ctx,
     653             :                                 bool do_seal,
     654             :                                 uint8_t *data, size_t length,
     655             :                                 const uint8_t *whole_pdu, size_t pdu_length,
     656             :                                 DATA_BLOB *sig)
     657             : {
     658       49157 :         uint32_t min_sig_size = 0;
     659       49157 :         uint32_t used_sig_size = 0;
     660        5348 :         uint8_t header[8];
     661        5348 :         uint8_t checksum[32];
     662       49157 :         uint32_t checksum_length = sizeof(checksum_length);
     663        5348 :         uint8_t _confounder[8];
     664       49157 :         uint8_t *confounder = NULL;
     665       49157 :         uint32_t confounder_ofs = 0;
     666        5348 :         uint8_t seq_num[8];
     667       49157 :         const uint8_t *sign_data = NULL;
     668       49157 :         size_t sign_length = 0;
     669        5348 :         NTSTATUS status;
     670             : 
     671       49157 :         netsec_offset_and_sizes(state,
     672             :                                 do_seal,
     673             :                                 &min_sig_size,
     674             :                                 &used_sig_size,
     675             :                                 &checksum_length,
     676             :                                 &confounder_ofs);
     677             : 
     678       49157 :         SETUP_SEQNUM(state, seq_num, state->initiator);
     679             : 
     680       49157 :         if (do_seal) {
     681       34974 :                 confounder = _confounder;
     682       34974 :                 generate_random_buffer(confounder, 8);
     683             :         } else {
     684       11655 :                 confounder = NULL;
     685             :         }
     686             : 
     687       49157 :         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     688       43599 :                 sign_data = whole_pdu;
     689       43599 :                 sign_length = pdu_length;
     690             :         } else {
     691         210 :                 sign_data = data;
     692         210 :                 sign_length = length;
     693             :         }
     694             : 
     695       49157 :         status = netsec_do_sign(state,
     696             :                                 confounder,
     697             :                                 sign_data,
     698             :                                 sign_length,
     699             :                                 header,
     700             :                                 checksum);
     701       49157 :         if (!NT_STATUS_IS_OK(status)) {
     702           0 :                 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
     703           0 :                 return NT_STATUS_ACCESS_DENIED;
     704             :         }
     705             : 
     706       49157 :         if (do_seal) {
     707       34974 :                 status = netsec_do_seal(state,
     708             :                                         seq_num,
     709             :                                         confounder,
     710             :                                         data,
     711             :                                         length,
     712             :                                         true);
     713       34974 :                 if (!NT_STATUS_IS_OK(status)) {
     714           0 :                         DBG_WARNING("netsec_do_seal failed: %s\n",
     715             :                                     nt_errstr(status));
     716           0 :                         return status;
     717             :                 }
     718             :         }
     719             : 
     720       49157 :         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
     721       49157 :         if (!NT_STATUS_IS_OK(status)) {
     722           0 :                 DBG_WARNING("netsec_do_seq_num failed: %s\n",
     723             :                             nt_errstr(status));
     724           0 :                 return status;
     725             :         }
     726             : 
     727       49157 :         (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
     728             : 
     729       49157 :         memcpy(sig->data, header, 8);
     730       49157 :         memcpy(sig->data+8, seq_num, 8);
     731       49157 :         memcpy(sig->data+16, checksum, checksum_length);
     732             : 
     733       49157 :         if (confounder) {
     734       34974 :                 memcpy(sig->data+confounder_ofs, confounder, 8);
     735             :         }
     736             : 
     737       49157 :         dump_data_pw("signature:", sig->data+ 0, 8);
     738       49157 :         dump_data_pw("seq_num  :", sig->data+ 8, 8);
     739       49157 :         dump_data_pw("digest   :", sig->data+16, checksum_length);
     740       49157 :         dump_data_pw("confound :", sig->data+confounder_ofs, 8);
     741             : 
     742       49157 :         return NT_STATUS_OK;
     743             : }
     744             : 
     745             : _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
     746             : 
     747       49157 : static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
     748             : {
     749        5348 :         struct schannel_state *state =
     750       49157 :                 talloc_get_type_abort(gensec_security->private_data,
     751             :                 struct schannel_state);
     752             : 
     753       49157 :         return netsec_outgoing_sig_size(state);
     754             : }
     755             : 
     756             : struct schannel_update_state {
     757             :         NTSTATUS status;
     758             :         DATA_BLOB out;
     759             : };
     760             : 
     761             : static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
     762             :                                          TALLOC_CTX *out_mem_ctx,
     763             :                                          const DATA_BLOB in, DATA_BLOB *out);
     764             : 
     765        7500 : static struct tevent_req *schannel_update_send(TALLOC_CTX *mem_ctx,
     766             :                                                struct tevent_context *ev,
     767             :                                                struct gensec_security *gensec_security,
     768             :                                                const DATA_BLOB in)
     769             : {
     770         960 :         struct tevent_req *req;
     771        7500 :         struct schannel_update_state *state = NULL;
     772         960 :         NTSTATUS status;
     773             : 
     774        7500 :         req = tevent_req_create(mem_ctx, &state,
     775             :                                 struct schannel_update_state);
     776        7500 :         if (req == NULL) {
     777           0 :                 return NULL;
     778             :         }
     779             : 
     780        8460 :         status = schannel_update_internal(gensec_security,
     781             :                                           state, in,
     782        7500 :                                           &state->out);
     783        7500 :         state->status = status;
     784        7500 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     785        2488 :                 status = NT_STATUS_OK;
     786             :         }
     787        7500 :         if (tevent_req_nterror(req, status)) {
     788           0 :                 return tevent_req_post(req, ev);
     789             :         }
     790             : 
     791        7500 :         tevent_req_done(req);
     792        7500 :         return tevent_req_post(req, ev);
     793             : }
     794             : 
     795        7500 : static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
     796             :                                          TALLOC_CTX *out_mem_ctx,
     797             :                                          const DATA_BLOB in, DATA_BLOB *out)
     798             : {
     799         960 :         struct schannel_state *state =
     800        7500 :                 talloc_get_type(gensec_security->private_data,
     801             :                 struct schannel_state);
     802         960 :         NTSTATUS status;
     803         960 :         enum ndr_err_code ndr_err;
     804        7500 :         struct NL_AUTH_MESSAGE bind_schannel = {
     805             :                 .Flags = 0,
     806             :         };
     807         960 :         struct NL_AUTH_MESSAGE bind_schannel_ack;
     808         960 :         struct netlogon_creds_CredentialState *creds;
     809         960 :         const char *workstation;
     810         960 :         const char *domain;
     811             : 
     812        7500 :         *out = data_blob(NULL, 0);
     813             : 
     814        7500 :         if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
     815           0 :                 switch (gensec_security->gensec_role) {
     816           0 :                 case GENSEC_CLIENT:
     817           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     818           0 :                 case GENSEC_SERVER:
     819           0 :                         return NT_STATUS_INVALID_PARAMETER;
     820             :                 }
     821           0 :                 return NT_STATUS_INTERNAL_ERROR;
     822             :         }
     823             : 
     824        7500 :         switch (gensec_security->gensec_role) {
     825        4976 :         case GENSEC_CLIENT:
     826        4976 :                 if (state != NULL) {
     827             :                         /* we could parse the bind ack, but we don't know what it is yet */
     828        2488 :                         return NT_STATUS_OK;
     829             :                 }
     830             : 
     831        2488 :                 creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
     832        2488 :                 if (creds == NULL) {
     833           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     834             :                 }
     835             : 
     836        2488 :                 state = netsec_create_state(gensec_security,
     837             :                                             creds, true /* initiator */);
     838        2488 :                 if (state == NULL) {
     839           0 :                         return NT_STATUS_NO_MEMORY;
     840             :                 }
     841             : 
     842        2488 :                 bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
     843             : 
     844        2488 :                 bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
     845             :                                       NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
     846        2488 :                 bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
     847        2488 :                 bind_schannel.oem_netbios_computer.a = creds->computer_name;
     848             : 
     849        2488 :                 if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
     850          72 :                         bind_schannel.Flags |= NL_FLAG_UTF8_DNS_DOMAIN_NAME;
     851          72 :                         bind_schannel.utf8_dns_domain.u = cli_credentials_get_realm(gensec_security->credentials);
     852             : 
     853          72 :                         bind_schannel.Flags |= NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME;
     854          72 :                         bind_schannel.utf8_netbios_computer.u = creds->computer_name;
     855             :                 }
     856             : 
     857        2488 :                 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
     858             :                                                (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
     859        2488 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     860           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     861           0 :                         DEBUG(3, ("Could not create schannel bind: %s\n",
     862             :                                   nt_errstr(status)));
     863           0 :                         return status;
     864             :                 }
     865             : 
     866        2488 :                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
     867        2524 :         case GENSEC_SERVER:
     868             : 
     869        2524 :                 if (state != NULL) {
     870             :                         /* no third leg on this protocol */
     871           0 :                         return NT_STATUS_INVALID_PARAMETER;
     872             :                 }
     873             : 
     874             :                 /* parse the schannel startup blob */
     875        2524 :                 ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
     876             :                         (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
     877        2524 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     878           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     879           0 :                         DEBUG(3, ("Could not parse incoming schannel bind: %s\n",
     880             :                                   nt_errstr(status)));
     881           0 :                         return status;
     882             :                 }
     883             : 
     884        2524 :                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
     885        2524 :                         domain = bind_schannel.oem_netbios_domain.a;
     886        2524 :                         if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) {
     887           0 :                                 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
     888             :                                           domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)));
     889           0 :                                 return NT_STATUS_LOGON_FAILURE;
     890             :                         }
     891           0 :                 } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) {
     892           0 :                         domain = bind_schannel.utf8_dns_domain.u;
     893           0 :                         if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) {
     894           0 :                                 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
     895             :                                           domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)));
     896           0 :                                 return NT_STATUS_LOGON_FAILURE;
     897             :                         }
     898             :                 } else {
     899           0 :                         DEBUG(3, ("Request for schannel to without domain\n"));
     900           0 :                         return NT_STATUS_LOGON_FAILURE;
     901             :                 }
     902             : 
     903        2524 :                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
     904        2524 :                         workstation = bind_schannel.oem_netbios_computer.a;
     905           0 :                 } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) {
     906           0 :                         workstation = bind_schannel.utf8_netbios_computer.u;
     907             :                 } else {
     908           0 :                         DEBUG(3, ("Request for schannel to without netbios workstation\n"));
     909           0 :                         return NT_STATUS_LOGON_FAILURE;
     910             :                 }
     911             : 
     912        2844 :                 status = schannel_get_creds_state(out_mem_ctx,
     913        2524 :                                                   gensec_security->settings->lp_ctx,
     914             :                                                   workstation, &creds);
     915        2524 :                 if (!NT_STATUS_IS_OK(status)) {
     916           0 :                         DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
     917             :                                   workstation, nt_errstr(status)));
     918           0 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
     919           0 :                                 return NT_STATUS_LOGON_FAILURE;
     920             :                         }
     921           0 :                         return status;
     922             :                 }
     923             : 
     924        2524 :                 state = netsec_create_state(gensec_security,
     925             :                                             creds, false /* not initiator */);
     926        2524 :                 if (state == NULL) {
     927           0 :                         return NT_STATUS_NO_MEMORY;
     928             :                 }
     929             : 
     930        2524 :                 status = auth_anonymous_user_info_dc(state,
     931        2524 :                                 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
     932             :                                 &state->user_info_dc);
     933        2524 :                 if (!NT_STATUS_IS_OK(status)) {
     934           0 :                         return status;
     935             :                 }
     936             : 
     937        2524 :                 bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
     938        2524 :                 bind_schannel_ack.Flags = 0;
     939        2524 :                 bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
     940             :                                                             * this does not have
     941             :                                                             * any meaning here
     942             :                                                             * - gd */
     943             : 
     944        2524 :                 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack,
     945             :                                                (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
     946        2524 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     947           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     948           0 :                         DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
     949             :                                   workstation, nt_errstr(status)));
     950           0 :                         return status;
     951             :                 }
     952             : 
     953        2524 :                 return NT_STATUS_OK;
     954             :         }
     955           0 :         return NT_STATUS_INVALID_PARAMETER;
     956             : }
     957             : 
     958        7500 : static NTSTATUS schannel_update_recv(struct tevent_req *req,
     959             :                                      TALLOC_CTX *out_mem_ctx,
     960             :                                      DATA_BLOB *out)
     961             : {
     962         960 :         struct schannel_update_state *state =
     963        7500 :                 tevent_req_data(req,
     964             :                 struct schannel_update_state);
     965         960 :         NTSTATUS status;
     966             : 
     967        7500 :         *out = data_blob_null;
     968             : 
     969        7500 :         if (tevent_req_is_nterror(req, &status)) {
     970           0 :                 tevent_req_received(req);
     971           0 :                 return status;
     972             :         }
     973             : 
     974        7500 :         status = state->status;
     975        7500 :         talloc_steal(out_mem_ctx, state->out.data);
     976        7500 :         *out = state->out;
     977        7500 :         tevent_req_received(req);
     978        7500 :         return status;
     979             : }
     980             : 
     981             : /**
     982             :  * Returns anonymous credentials for schannel, matching Win2k3.
     983             :  *
     984             :  */
     985             : 
     986        2524 : static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
     987             :                                       TALLOC_CTX *mem_ctx,
     988             :                                       struct auth_session_info **_session_info)
     989             : {
     990         320 :         struct schannel_state *state =
     991        2524 :                 talloc_get_type(gensec_security->private_data,
     992             :                 struct schannel_state);
     993        2524 :         struct auth4_context *auth_ctx = gensec_security->auth_context;
     994        2524 :         struct auth_session_info *session_info = NULL;
     995        2524 :         uint32_t session_info_flags = 0;
     996         320 :         NTSTATUS status;
     997             : 
     998        2524 :         if (auth_ctx == NULL) {
     999           0 :                 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
    1000           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1001             :         }
    1002             : 
    1003        2524 :         if (auth_ctx->generate_session_info == NULL) {
    1004           0 :                 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
    1005           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1006             :         }
    1007             : 
    1008        2524 :         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
    1009           0 :                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
    1010             :         }
    1011             : 
    1012        2524 :         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
    1013             : 
    1014        2524 :         status = auth_ctx->generate_session_info(
    1015             :                                 auth_ctx,
    1016             :                                 mem_ctx,
    1017        2204 :                                 state->user_info_dc,
    1018        2524 :                                 state->user_info_dc->info->account_name,
    1019             :                                 session_info_flags,
    1020             :                                 &session_info);
    1021        2524 :         if (!NT_STATUS_IS_OK(status)) {
    1022           0 :                 return status;
    1023             :         }
    1024             : 
    1025        2524 :         *_session_info = session_info;
    1026        2524 :         return NT_STATUS_OK;
    1027             : }
    1028             : 
    1029             : /*
    1030             :  * Reduce the attack surface by ensuring schannel is not available when
    1031             :  * we are not a DC
    1032             :  */
    1033        2524 : static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
    1034             : {
    1035        2844 :         enum server_role server_role
    1036        2524 :                 = lpcfg_server_role(gensec_security->settings->lp_ctx);
    1037             : 
    1038        2524 :         switch (server_role) {
    1039        2524 :         case ROLE_DOMAIN_BDC:
    1040             :         case ROLE_DOMAIN_PDC:
    1041             :         case ROLE_ACTIVE_DIRECTORY_DC:
    1042             :         case ROLE_IPA_DC:
    1043        2524 :                 return NT_STATUS_OK;
    1044           0 :         default:
    1045           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1046             :         }
    1047             : }
    1048             : 
    1049        2488 : static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
    1050             : {
    1051        2488 :         return NT_STATUS_OK;
    1052             : }
    1053             : 
    1054      443642 : static bool schannel_have_feature(struct gensec_security *gensec_security,
    1055             :                                          uint32_t feature)
    1056             : {
    1057      443642 :         if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
    1058      443642 :                 if (feature & GENSEC_FEATURE_SIGN) {
    1059      138712 :                         return true;
    1060             :                 }
    1061             :         }
    1062      287910 :         if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
    1063      255356 :                 if (feature & GENSEC_FEATURE_SEAL) {
    1064      100946 :                         return true;
    1065             :                 }
    1066             :         }
    1067      178000 :         if (feature & GENSEC_FEATURE_DCE_STYLE) {
    1068       96442 :                 return true;
    1069             :         }
    1070       73098 :         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1071        7500 :                 return true;
    1072             :         }
    1073       57282 :         return false;
    1074             : }
    1075             : 
    1076             : /*
    1077             :   unseal a packet
    1078             : */
    1079       34954 : static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
    1080             :                                        uint8_t *data, size_t length,
    1081             :                                        const uint8_t *whole_pdu, size_t pdu_length,
    1082             :                                        const DATA_BLOB *sig)
    1083             : {
    1084        2820 :         struct schannel_state *state =
    1085       34954 :                 talloc_get_type_abort(gensec_security->private_data,
    1086             :                 struct schannel_state);
    1087             : 
    1088       34954 :         return netsec_incoming_packet(state, true,
    1089             :                                       discard_const_p(uint8_t, data),
    1090             :                                       length,
    1091             :                                       whole_pdu, pdu_length,
    1092             :                                       sig);
    1093             : }
    1094             : 
    1095             : /*
    1096             :   check the signature on a packet
    1097             : */
    1098       14141 : static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
    1099             :                                       const uint8_t *data, size_t length,
    1100             :                                       const uint8_t *whole_pdu, size_t pdu_length,
    1101             :                                       const DATA_BLOB *sig)
    1102             : {
    1103        2528 :         struct schannel_state *state =
    1104       14141 :                 talloc_get_type_abort(gensec_security->private_data,
    1105             :                 struct schannel_state);
    1106             : 
    1107       14141 :         return netsec_incoming_packet(state, false,
    1108             :                                       discard_const_p(uint8_t, data),
    1109             :                                       length,
    1110             :                                       whole_pdu, pdu_length,
    1111             :                                       sig);
    1112             : }
    1113             : /*
    1114             :   seal a packet
    1115             : */
    1116       34974 : static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
    1117             :                                      TALLOC_CTX *mem_ctx,
    1118             :                                      uint8_t *data, size_t length,
    1119             :                                      const uint8_t *whole_pdu, size_t pdu_length,
    1120             :                                      DATA_BLOB *sig)
    1121             : {
    1122        2820 :         struct schannel_state *state =
    1123       34974 :                 talloc_get_type_abort(gensec_security->private_data,
    1124             :                 struct schannel_state);
    1125             : 
    1126       34974 :         return netsec_outgoing_packet(state, mem_ctx, true,
    1127             :                                       data, length,
    1128             :                                       whole_pdu, pdu_length,
    1129             :                                       sig);
    1130             : }
    1131             : 
    1132             : /*
    1133             :   sign a packet
    1134             : */
    1135       14183 : static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
    1136             :                                      TALLOC_CTX *mem_ctx,
    1137             :                                      const uint8_t *data, size_t length,
    1138             :                                      const uint8_t *whole_pdu, size_t pdu_length,
    1139             :                                      DATA_BLOB *sig)
    1140             : {
    1141        2528 :         struct schannel_state *state =
    1142       14183 :                 talloc_get_type_abort(gensec_security->private_data,
    1143             :                 struct schannel_state);
    1144             : 
    1145       14183 :         return netsec_outgoing_packet(state, mem_ctx, false,
    1146             :                                       discard_const_p(uint8_t, data),
    1147             :                                       length,
    1148             :                                       whole_pdu, pdu_length,
    1149             :                                       sig);
    1150             : }
    1151             : 
    1152             : static const struct gensec_security_ops gensec_schannel_security_ops = {
    1153             :         .name           = "schannel",
    1154             :         .auth_type      = DCERPC_AUTH_TYPE_SCHANNEL,
    1155             :         .client_start   = schannel_client_start,
    1156             :         .server_start   = schannel_server_start,
    1157             :         .update_send    = schannel_update_send,
    1158             :         .update_recv    = schannel_update_recv,
    1159             :         .seal_packet    = schannel_seal_packet,
    1160             :         .sign_packet    = schannel_sign_packet,
    1161             :         .check_packet   = schannel_check_packet,
    1162             :         .unseal_packet  = schannel_unseal_packet,
    1163             :         .session_info   = schannel_session_info,
    1164             :         .sig_size       = schannel_sig_size,
    1165             :         .have_feature   = schannel_have_feature,
    1166             :         .enabled        = true,
    1167             :         .priority       = GENSEC_SCHANNEL
    1168             : };
    1169             : 
    1170       61098 : _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
    1171             : {
    1172        1228 :         NTSTATUS ret;
    1173       61098 :         ret = gensec_register(ctx, &gensec_schannel_security_ops);
    1174       61098 :         if (!NT_STATUS_IS_OK(ret)) {
    1175           0 :                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
    1176             :                         gensec_schannel_security_ops.name));
    1177           0 :                 return ret;
    1178             :         }
    1179             : 
    1180       61098 :         return ret;
    1181             : }

Generated by: LCOV version 1.14