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

Generated by: LCOV version 1.13