LCOV - code coverage report
Current view: top level - auth/gensec - schannel.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 389 512 76.0 %
Date: 2024-06-13 04:01:37 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             : #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        2115 : 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        2115 :         state = talloc_zero(gensec, struct schannel_state);
      76        2115 :         if (state == NULL) {
      77           0 :                 return NULL;
      78             :         }
      79             : 
      80        2115 :         state->gensec = gensec;
      81        2115 :         state->initiator = initiator;
      82        2115 :         state->creds = netlogon_creds_copy(state, creds);
      83        2115 :         if (state->creds == NULL) {
      84           0 :                 talloc_free(state);
      85           0 :                 return NULL;
      86             :         }
      87             : 
      88        2115 :         gensec->private_data = state;
      89             : 
      90        2115 :         return state;
      91             : }
      92             : 
      93       86875 : 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       86875 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     106       37441 :                 min_sig_size = 48;
     107       37441 :                 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       37441 :                 checksum_length = 8;
     115       37441 :                 confounder_ofs = 24;
     116             :         } else {
     117       49434 :                 min_sig_size = 24;
     118       49434 :                 used_sig_size = 32;
     119       49434 :                 checksum_length = 8;
     120       49434 :                 confounder_ofs = 24;
     121             :         }
     122             : 
     123       86875 :         if (do_seal) {
     124       75499 :                 min_sig_size += 8;
     125             :         }
     126             : 
     127       86875 :         if (_min_sig_size) {
     128       57922 :                 *_min_sig_size = min_sig_size;
     129             :         }
     130             : 
     131       86875 :         if (_used_sig_size) {
     132       57906 :                 *_used_sig_size = used_sig_size;
     133             :         }
     134             : 
     135       86875 :         if (_checksum_length) {
     136       57922 :                 *_checksum_length = checksum_length;
     137             :         }
     138             : 
     139       86875 :         if (_confounder_ofs) {
     140       57922 :                 *_confounder_ofs = confounder_ofs;
     141             :         }
     142       86875 : }
     143             : 
     144             : /*******************************************************************
     145             :  Encode or Decode the sequence number (which is symmetric)
     146             :  ********************************************************************/
     147       57922 : 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       57922 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     153             : #ifdef HAVE_GNUTLS_AES_CFB8
     154        2354 :                 gnutls_cipher_hd_t cipher_hnd = NULL;
     155        2354 :                 gnutls_datum_t key = {
     156        2354 :                         .data = state->creds->session_key,
     157             :                         .size = sizeof(state->creds->session_key),
     158             :                 };
     159             :                 uint32_t iv_size =
     160        2354 :                         gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
     161        2354 :                 uint8_t _iv[iv_size];
     162        2354 :                 gnutls_datum_t iv = {
     163             :                         .data = _iv,
     164             :                         .size = iv_size,
     165             :                 };
     166             :                 int rc;
     167             : 
     168        2354 :                 ZERO_ARRAY(_iv);
     169             : 
     170        2354 :                 memcpy(iv.data + 0, checksum, 8);
     171        2354 :                 memcpy(iv.data + 8, checksum, 8);
     172             : 
     173        2354 :                 rc = gnutls_cipher_init(&cipher_hnd,
     174             :                                         GNUTLS_CIPHER_AES_128_CFB8,
     175             :                                         &key,
     176             :                                         &iv);
     177        2354 :                 if (rc < 0) {
     178           0 :                         return gnutls_error_to_ntstatus(rc,
     179             :                                                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
     180             :                 }
     181             : 
     182        2354 :                 rc = gnutls_cipher_encrypt(cipher_hnd, seq_num, 8);
     183        2354 :                 gnutls_cipher_deinit(cipher_hnd);
     184        2354 :                 if (rc < 0) {
     185           0 :                         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       22612 :                 AES_set_encrypt_key(state->creds->session_key, 128, &key);
     194       22612 :                 ZERO_STRUCT(iv);
     195       22612 :                 memcpy(iv+0, checksum, 8);
     196       22612 :                 memcpy(iv+8, checksum, 8);
     197             : 
     198       22612 :                 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       32956 :                 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       32956 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     212       32956 :                                       state->creds->session_key,
     213             :                                       sizeof(state->creds->session_key),
     214             :                                       zeros,
     215             :                                       sizeof(zeros),
     216             :                                       digest1);
     217       32956 :                 if (rc < 0) {
     218           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     219             :                 }
     220             : 
     221       32956 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     222             :                                       digest1,
     223             :                                       sizeof(digest1),
     224             :                                       checksum,
     225             :                                       checksum_length,
     226             :                                       _sequence_key);
     227       32956 :                 if (rc < 0) {
     228           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     229             :                 }
     230             : 
     231       32956 :                 ZERO_ARRAY(digest1);
     232             : 
     233       32956 :                 rc = gnutls_cipher_init(&cipher_hnd,
     234             :                                         GNUTLS_CIPHER_ARCFOUR_128,
     235             :                                         &sequence_key,
     236             :                                         NULL);
     237       32956 :                 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       32956 :                 rc = gnutls_cipher_encrypt(cipher_hnd,
     243             :                                            seq_num,
     244             :                                            8);
     245       32956 :                 gnutls_cipher_deinit(cipher_hnd);
     246       32956 :                 ZERO_ARRAY(_sequence_key);
     247       32956 :                 if (rc < 0) {
     248           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     249             :                 }
     250             :         }
     251             : 
     252       57922 :         state->seq_num++;
     253             : 
     254       57922 :         return NT_STATUS_OK;
     255             : }
     256             : 
     257       46546 : 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       46546 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     264             : #ifdef HAVE_GNUTLS_AES_CFB8
     265        2354 :                 gnutls_cipher_hd_t cipher_hnd = NULL;
     266        2354 :                 uint8_t sess_kf0[16] = {0};
     267        2354 :                 gnutls_datum_t key = {
     268             :                         .data = sess_kf0,
     269             :                         .size = sizeof(sess_kf0),
     270             :                 };
     271             :                 uint32_t iv_size =
     272        2354 :                         gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
     273        2354 :                 uint8_t _iv[iv_size];
     274        2354 :                 gnutls_datum_t iv = {
     275             :                         .data = _iv,
     276             :                         .size = iv_size,
     277             :                 };
     278             :                 uint32_t i;
     279             :                 int rc;
     280             : 
     281       40018 :                 for (i = 0; i < key.size; i++) {
     282       37664 :                         key.data[i] = state->creds->session_key[i] ^ 0xf0;
     283             :                 }
     284             : 
     285        2354 :                 ZERO_ARRAY(_iv);
     286             : 
     287        2354 :                 memcpy(iv.data + 0, seq_num, 8);
     288        2354 :                 memcpy(iv.data + 8, seq_num, 8);
     289             : 
     290        2354 :                 rc = gnutls_cipher_init(&cipher_hnd,
     291             :                                         GNUTLS_CIPHER_AES_128_CFB8,
     292             :                                         &key,
     293             :                                         &iv);
     294        2354 :                 if (rc < 0) {
     295           0 :                         DBG_ERR("ERROR: gnutls_cipher_init: %s\n",
     296             :                                 gnutls_strerror(rc));
     297           0 :                         return NT_STATUS_NO_MEMORY;
     298             :                 }
     299             : 
     300        2354 :                 if (forward) {
     301        1173 :                         rc = gnutls_cipher_encrypt(cipher_hnd,
     302             :                                                    confounder,
     303             :                                                    8);
     304        1173 :                         if (rc < 0) {
     305           0 :                                 gnutls_cipher_deinit(cipher_hnd);
     306           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     307             :                         }
     308             : 
     309        1173 :                         rc = gnutls_cipher_encrypt(cipher_hnd,
     310             :                                                    data,
     311             :                                                    length);
     312        1173 :                         if (rc < 0) {
     313           0 :                                 gnutls_cipher_deinit(cipher_hnd);
     314           0 :                                 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        1181 :                         uint8_t tmp[16] = { 0, };
     328        1181 :                         uint32_t tmp_dlength = MIN(length, sizeof(tmp) - 8);
     329             : 
     330        1181 :                         memcpy(tmp, confounder, 8);
     331        1181 :                         memcpy(tmp + 8, data, tmp_dlength);
     332             : 
     333        1181 :                         rc = gnutls_cipher_decrypt(cipher_hnd,
     334             :                                                    tmp,
     335        1181 :                                                    8 + tmp_dlength);
     336        1181 :                         if (rc < 0) {
     337           0 :                                 ZERO_STRUCT(tmp);
     338           0 :                                 gnutls_cipher_deinit(cipher_hnd);
     339           0 :                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     340             :                         }
     341             : 
     342        1181 :                         memcpy(confounder, tmp, 8);
     343        1181 :                         memcpy(data, tmp + 8, tmp_dlength);
     344        1181 :                         ZERO_STRUCT(tmp);
     345             : 
     346        1181 :                         if (length > tmp_dlength) {
     347        1181 :                                 rc = gnutls_cipher_decrypt(cipher_hnd,
     348        1181 :                                                            data + tmp_dlength,
     349        1181 :                                                            length - tmp_dlength);
     350        1181 :                                 if (rc < 0) {
     351           0 :                                         gnutls_cipher_deinit(cipher_hnd);
     352           0 :                                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     353             :                                 }
     354             :                         }
     355             :                 }
     356        2354 :                 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      253436 :                 for (i = 0; i < 16; i++) {
     364      238528 :                         sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
     365             :                 }
     366             : 
     367       14908 :                 AES_set_encrypt_key(sess_kf0, 128, &key);
     368       14908 :                 ZERO_STRUCT(iv);
     369       14908 :                 memcpy(iv+0, seq_num, 8);
     370       14908 :                 memcpy(iv+8, seq_num, 8);
     371             : 
     372       14908 :                 if (forward) {
     373        7450 :                         aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT);
     374        7450 :                         aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT);
     375             :                 } else {
     376        7458 :                         aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT);
     377        7458 :                         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       29284 :                 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      497828 :                 for (i = 0; i < 16; i++) {
     394      468544 :                         sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
     395             :                 }
     396             : 
     397       29284 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     398             :                                       sess_kf0,
     399             :                                       sizeof(sess_kf0),
     400             :                                       zeros,
     401             :                                       4,
     402             :                                       digest2);
     403       29284 :                 if (rc < 0) {
     404           0 :                         ZERO_ARRAY(digest2);
     405           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     406             :                 }
     407             : 
     408       29284 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     409             :                                       digest2,
     410             :                                       sizeof(digest2),
     411             :                                       seq_num,
     412             :                                       8,
     413             :                                       _sealing_key);
     414             : 
     415       29284 :                 ZERO_ARRAY(digest2);
     416       29284 :                 if (rc < 0) {
     417           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     418             :                 }
     419             : 
     420       29284 :                 rc = gnutls_cipher_init(&cipher_hnd,
     421             :                                         GNUTLS_CIPHER_ARCFOUR_128,
     422             :                                         &sealing_key,
     423             :                                         NULL);
     424       29284 :                 if (rc < 0) {
     425           0 :                         ZERO_ARRAY(_sealing_key);
     426           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     427             :                 }
     428       29284 :                 rc = gnutls_cipher_encrypt(cipher_hnd,
     429             :                                            confounder,
     430             :                                            8);
     431       29284 :                 if (rc < 0) {
     432           0 :                         ZERO_ARRAY(_sealing_key);
     433           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     434             :                 }
     435       29284 :                 gnutls_cipher_deinit(cipher_hnd);
     436       29284 :                 rc = gnutls_cipher_init(&cipher_hnd,
     437             :                                         GNUTLS_CIPHER_ARCFOUR_128,
     438             :                                         &sealing_key,
     439             :                                         NULL);
     440       29284 :                 if (rc < 0) {
     441           0 :                         ZERO_ARRAY(_sealing_key);
     442           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     443             :                 }
     444       29284 :                 rc = gnutls_cipher_encrypt(cipher_hnd,
     445             :                                            data,
     446             :                                            length);
     447       29284 :                 gnutls_cipher_deinit(cipher_hnd);
     448       29284 :                 ZERO_ARRAY(_sealing_key);
     449       29284 :                 if (rc < 0) {
     450           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     451             :                 }
     452             :         }
     453             : 
     454       46546 :         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       57922 : 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       57922 :         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     468       24966 :                 gnutls_hmac_hd_t hmac_hnd = NULL;
     469             :                 int rc;
     470             : 
     471       24966 :                 rc = gnutls_hmac_init(&hmac_hnd,
     472             :                                       GNUTLS_MAC_SHA256,
     473       24966 :                                       state->creds->session_key,
     474             :                                       sizeof(state->creds->session_key));
     475       24966 :                 if (rc < 0) {
     476           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     477             :                 }
     478             : 
     479       24966 :                 if (confounder) {
     480       17262 :                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
     481       17262 :                         SSVAL(header, 2, NL_SEAL_AES128);
     482       17262 :                         SSVAL(header, 4, 0xFFFF);
     483       17262 :                         SSVAL(header, 6, 0x0000);
     484             : 
     485       17262 :                         rc = gnutls_hmac(hmac_hnd, header, 8);
     486       17262 :                         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       17262 :                         rc = gnutls_hmac(hmac_hnd, confounder, 8);
     491       17262 :                         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        7704 :                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
     497        7704 :                         SSVAL(header, 2, NL_SEAL_NONE);
     498        7704 :                         SSVAL(header, 4, 0xFFFF);
     499        7704 :                         SSVAL(header, 6, 0x0000);
     500             : 
     501        7704 :                         rc = gnutls_hmac(hmac_hnd, header, 8);
     502        7704 :                         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       24966 :                 rc = gnutls_hmac(hmac_hnd, data, length);
     509       24966 :                 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       24966 :                 gnutls_hmac_deinit(hmac_hnd, checksum);
     515             :         } else {
     516             :                 uint8_t packet_digest[16];
     517             :                 static const uint8_t zeros[4];
     518       32956 :                 gnutls_hash_hd_t hash_hnd = NULL;
     519             :                 int rc;
     520             : 
     521       32956 :                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
     522       32956 :                 if (rc < 0) {
     523           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     524             :                 }
     525             : 
     526       32956 :                 rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
     527       32956 :                 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       32956 :                 if (confounder) {
     532       29284 :                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
     533       29284 :                         SSVAL(header, 2, NL_SEAL_RC4);
     534       29284 :                         SSVAL(header, 4, 0xFFFF);
     535       29284 :                         SSVAL(header, 6, 0x0000);
     536             : 
     537       29284 :                         rc = gnutls_hash(hash_hnd, header, 8);
     538       29284 :                         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       29284 :                         rc = gnutls_hash(hash_hnd, confounder, 8);
     543       29284 :                         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        3672 :                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
     549        3672 :                         SSVAL(header, 2, NL_SEAL_NONE);
     550        3672 :                         SSVAL(header, 4, 0xFFFF);
     551        3672 :                         SSVAL(header, 6, 0x0000);
     552             : 
     553        3672 :                         rc = gnutls_hash(hash_hnd, header, 8);
     554        3672 :                         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       32956 :                 rc = gnutls_hash(hash_hnd, data, length);
     560       32956 :                 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       32956 :                 gnutls_hash_deinit(hash_hnd, packet_digest);
     565             : 
     566       32956 :                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
     567       32956 :                                       state->creds->session_key,
     568             :                                       sizeof(state->creds->session_key),
     569             :                                       packet_digest,
     570             :                                       sizeof(packet_digest),
     571             :                                       checksum);
     572       32956 :                 ZERO_ARRAY(packet_digest);
     573       32956 :                 if (rc < 0) {
     574           0 :                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     575             :                 }
     576             :         }
     577             : 
     578       57922 :         return NT_STATUS_OK;
     579             : }
     580             : 
     581       28969 : 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       28969 :         uint32_t min_sig_size = 0;
     588             :         uint8_t header[8];
     589             :         uint8_t checksum[32];
     590       28969 :         uint32_t checksum_length = sizeof(checksum_length);
     591             :         uint8_t _confounder[8];
     592       28969 :         uint8_t *confounder = NULL;
     593       28969 :         uint32_t confounder_ofs = 0;
     594             :         uint8_t seq_num[8];
     595             :         bool ret;
     596       28969 :         const uint8_t *sign_data = NULL;
     597       28969 :         size_t sign_length = 0;
     598             :         NTSTATUS status;
     599             : 
     600       28969 :         netsec_offset_and_sizes(state,
     601             :                                 do_unseal,
     602             :                                 &min_sig_size,
     603             :                                 NULL,
     604             :                                 &checksum_length,
     605             :                                 &confounder_ofs);
     606             : 
     607       28969 :         if (sig->length < min_sig_size) {
     608           0 :                 return NT_STATUS_ACCESS_DENIED;
     609             :         }
     610             : 
     611       28969 :         if (do_unseal) {
     612       23281 :                 confounder = _confounder;
     613       23281 :                 memcpy(confounder, sig->data+confounder_ofs, 8);
     614             :         } else {
     615        5688 :                 confounder = NULL;
     616             :         }
     617             : 
     618       28969 :         SETUP_SEQNUM(state, seq_num, !state->initiator);
     619             : 
     620       28969 :         if (do_unseal) {
     621       23281 :                 status = netsec_do_seal(state,
     622             :                                         seq_num,
     623             :                                         confounder,
     624             :                                         data,
     625             :                                         length,
     626             :                                         false);
     627       23281 :                 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       28969 :         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     634       28799 :                 sign_data = whole_pdu;
     635       28799 :                 sign_length = pdu_length;
     636             :         } else {
     637         170 :                 sign_data = data;
     638         170 :                 sign_length = length;
     639             :         }
     640             : 
     641       28969 :         status = netsec_do_sign(state,
     642             :                                 confounder,
     643             :                                 sign_data,
     644             :                                 sign_length,
     645             :                                 header,
     646             :                                 checksum);
     647       28969 :         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       28969 :         ret = mem_equal_const_time(checksum, sig->data+16, checksum_length);
     653       28969 :         if (!ret) {
     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       28969 :         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
     660       28969 :         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       28969 :         ZERO_ARRAY(checksum);
     667             : 
     668       28969 :         ret = mem_equal_const_time(seq_num, sig->data+8, 8);
     669       28969 :         if (!ret) {
     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       28969 :         return NT_STATUS_OK;
     676             : }
     677             : 
     678       28953 : static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
     679             : {
     680       28953 :         uint32_t sig_size = 0;
     681             : 
     682       28953 :         netsec_offset_and_sizes(state,
     683             :                                 true,
     684             :                                 NULL,
     685             :                                 &sig_size,
     686             :                                 NULL,
     687             :                                 NULL);
     688             : 
     689       28953 :         return sig_size;
     690             : }
     691             : 
     692       28953 : 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       28953 :         uint32_t min_sig_size = 0;
     700       28953 :         uint32_t used_sig_size = 0;
     701             :         uint8_t header[8];
     702             :         uint8_t checksum[32];
     703       28953 :         uint32_t checksum_length = sizeof(checksum_length);
     704             :         uint8_t _confounder[8];
     705       28953 :         uint8_t *confounder = NULL;
     706       28953 :         uint32_t confounder_ofs = 0;
     707             :         uint8_t seq_num[8];
     708       28953 :         const uint8_t *sign_data = NULL;
     709       28953 :         size_t sign_length = 0;
     710             :         NTSTATUS status;
     711             : 
     712       28953 :         netsec_offset_and_sizes(state,
     713             :                                 do_seal,
     714             :                                 &min_sig_size,
     715             :                                 &used_sig_size,
     716             :                                 &checksum_length,
     717             :                                 &confounder_ofs);
     718             : 
     719       28953 :         SETUP_SEQNUM(state, seq_num, state->initiator);
     720             : 
     721       28953 :         if (do_seal) {
     722       23265 :                 confounder = _confounder;
     723       23265 :                 generate_random_buffer(confounder, 8);
     724             :         } else {
     725        5688 :                 confounder = NULL;
     726             :         }
     727             : 
     728       28953 :         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     729       28783 :                 sign_data = whole_pdu;
     730       28783 :                 sign_length = pdu_length;
     731             :         } else {
     732         170 :                 sign_data = data;
     733         170 :                 sign_length = length;
     734             :         }
     735             : 
     736       28953 :         status = netsec_do_sign(state,
     737             :                                 confounder,
     738             :                                 sign_data,
     739             :                                 sign_length,
     740             :                                 header,
     741             :                                 checksum);
     742       28953 :         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       28953 :         if (do_seal) {
     748       23265 :                 status = netsec_do_seal(state,
     749             :                                         seq_num,
     750             :                                         confounder,
     751             :                                         data,
     752             :                                         length,
     753             :                                         true);
     754       23265 :                 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       28953 :         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
     762       28953 :         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       28953 :         (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
     769             : 
     770       28953 :         memcpy(sig->data, header, 8);
     771       28953 :         memcpy(sig->data+8, seq_num, 8);
     772       28953 :         memcpy(sig->data+16, checksum, checksum_length);
     773             : 
     774       28953 :         if (confounder) {
     775       23265 :                 memcpy(sig->data+confounder_ofs, confounder, 8);
     776             :         }
     777             : 
     778       28953 :         dump_data_pw("signature:", sig->data+ 0, 8);
     779       28953 :         dump_data_pw("seq_num  :", sig->data+ 8, 8);
     780       28953 :         dump_data_pw("digest   :", sig->data+16, checksum_length);
     781       28953 :         dump_data_pw("confound :", sig->data+confounder_ofs, 8);
     782             : 
     783       28953 :         return NT_STATUS_OK;
     784             : }
     785             : 
     786             : _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
     787             : 
     788       28953 : static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
     789             : {
     790       27780 :         struct schannel_state *state =
     791       28953 :                 talloc_get_type_abort(gensec_security->private_data,
     792             :                 struct schannel_state);
     793             : 
     794       28953 :         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        3103 : 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        3103 :         struct schannel_update_state *state = NULL;
     813             :         NTSTATUS status;
     814             : 
     815        3103 :         req = tevent_req_create(mem_ctx, &state,
     816             :                                 struct schannel_update_state);
     817        3103 :         if (req == NULL) {
     818           0 :                 return NULL;
     819             :         }
     820             : 
     821        3103 :         status = schannel_update_internal(gensec_security,
     822             :                                           state, in,
     823        3103 :                                           &state->out);
     824        3103 :         state->status = status;
     825        3103 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     826         988 :                 status = NT_STATUS_OK;
     827             :         }
     828        3103 :         if (tevent_req_nterror(req, status)) {
     829           0 :                 return tevent_req_post(req, ev);
     830             :         }
     831             : 
     832        3103 :         tevent_req_done(req);
     833        3103 :         return tevent_req_post(req, ev);
     834             : }
     835             : 
     836        3103 : 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        2979 :         struct schannel_state *state =
     841        3103 :                 talloc_get_type(gensec_security->private_data,
     842             :                 struct schannel_state);
     843             :         NTSTATUS status;
     844             :         enum ndr_err_code ndr_err;
     845        3103 :         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        3103 :         *out = data_blob(NULL, 0);
     854             : 
     855        3103 :         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        3103 :         switch (gensec_security->gensec_role) {
     866        1976 :         case GENSEC_CLIENT:
     867        1976 :                 if (state != NULL) {
     868             :                         /* we could parse the bind ack, but we don't know what it is yet */
     869         988 :                         return NT_STATUS_OK;
     870             :                 }
     871             : 
     872         988 :                 creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
     873         988 :                 if (creds == NULL) {
     874           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     875             :                 }
     876             : 
     877         988 :                 state = netsec_create_state(gensec_security,
     878             :                                             creds, true /* initiator */);
     879         988 :                 if (state == NULL) {
     880           0 :                         return NT_STATUS_NO_MEMORY;
     881             :                 }
     882             : 
     883         988 :                 bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
     884             : 
     885         988 :                 bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
     886             :                                       NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
     887         988 :                 bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
     888         988 :                 bind_schannel.oem_netbios_computer.a = creds->computer_name;
     889             : 
     890         988 :                 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         988 :                 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
     899             :                                                (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
     900         988 :                 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         988 :                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
     908        1127 :         case GENSEC_SERVER:
     909             : 
     910        1127 :                 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        1127 :                 ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
     917             :                         (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
     918        1127 :                 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        1127 :                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
     926        1127 :                         domain = bind_schannel.oem_netbios_domain.a;
     927        1127 :                         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        1127 :                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
     945        1127 :                         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        1127 :                 status = schannel_get_creds_state(out_mem_ctx,
     954        1127 :                                                   gensec_security->settings->lp_ctx,
     955             :                                                   workstation, &creds);
     956        1127 :                 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        1127 :                 state = netsec_create_state(gensec_security,
     966             :                                             creds, false /* not initiator */);
     967        1127 :                 if (state == NULL) {
     968           0 :                         return NT_STATUS_NO_MEMORY;
     969             :                 }
     970             : 
     971        2166 :                 status = auth_anonymous_user_info_dc(state,
     972        1127 :                                 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
     973             :                                 &state->user_info_dc);
     974        1127 :                 if (!NT_STATUS_IS_OK(status)) {
     975           0 :                         return status;
     976             :                 }
     977             : 
     978        1127 :                 bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
     979        1127 :                 bind_schannel_ack.Flags = 0;
     980        1127 :                 bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
     981             :                                                             * this does not have
     982             :                                                             * any meaning here
     983             :                                                             * - gd */
     984             : 
     985        1127 :                 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        1127 :                 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        1127 :                 return NT_STATUS_OK;
     995             :         }
     996           0 :         return NT_STATUS_INVALID_PARAMETER;
     997             : }
     998             : 
     999        3103 : static NTSTATUS schannel_update_recv(struct tevent_req *req,
    1000             :                                      TALLOC_CTX *out_mem_ctx,
    1001             :                                      DATA_BLOB *out)
    1002             : {
    1003        2979 :         struct schannel_update_state *state =
    1004        3103 :                 tevent_req_data(req,
    1005             :                 struct schannel_update_state);
    1006             :         NTSTATUS status;
    1007             : 
    1008        3103 :         *out = data_blob_null;
    1009             : 
    1010        3103 :         if (tevent_req_is_nterror(req, &status)) {
    1011           0 :                 tevent_req_received(req);
    1012           0 :                 return status;
    1013             :         }
    1014             : 
    1015        3103 :         status = state->status;
    1016        3103 :         talloc_steal(out_mem_ctx, state->out.data);
    1017        3103 :         *out = state->out;
    1018        3103 :         tevent_req_received(req);
    1019        3103 :         return status;
    1020             : }
    1021             : 
    1022             : /**
    1023             :  * Returns anonymous credentials for schannel, matching Win2k3.
    1024             :  *
    1025             :  */
    1026             : 
    1027        1127 : static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
    1028             :                                       TALLOC_CTX *mem_ctx,
    1029             :                                       struct auth_session_info **_session_info)
    1030             : {
    1031        1039 :         struct schannel_state *state =
    1032        1127 :                 talloc_get_type(gensec_security->private_data,
    1033             :                 struct schannel_state);
    1034        1127 :         struct auth4_context *auth_ctx = gensec_security->auth_context;
    1035        1127 :         struct auth_session_info *session_info = NULL;
    1036        1127 :         uint32_t session_info_flags = 0;
    1037             :         NTSTATUS status;
    1038             : 
    1039        1127 :         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        1127 :         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        1127 :         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
    1050           0 :                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
    1051             :         }
    1052             : 
    1053        1127 :         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
    1054             : 
    1055        3205 :         status = auth_ctx->generate_session_info(
    1056             :                                 auth_ctx,
    1057             :                                 mem_ctx,
    1058        1127 :                                 state->user_info_dc,
    1059        1127 :                                 state->user_info_dc->info->account_name,
    1060             :                                 session_info_flags,
    1061             :                                 &session_info);
    1062        1127 :         if (!NT_STATUS_IS_OK(status)) {
    1063           0 :                 return status;
    1064             :         }
    1065             : 
    1066        1127 :         *_session_info = session_info;
    1067        1127 :         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        1127 : static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
    1075             : {
    1076        1127 :         enum server_role server_role
    1077        1127 :                 = lpcfg_server_role(gensec_security->settings->lp_ctx);
    1078             : 
    1079        1127 :         switch (server_role) {
    1080        1127 :         case ROLE_DOMAIN_BDC:
    1081             :         case ROLE_DOMAIN_PDC:
    1082             :         case ROLE_ACTIVE_DIRECTORY_DC:
    1083             :         case ROLE_IPA_DC:
    1084        1127 :                 return NT_STATUS_OK;
    1085           0 :         default:
    1086           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1087             :         }
    1088             : }
    1089             : 
    1090         988 : static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
    1091             : {
    1092         988 :         return NT_STATUS_OK;
    1093             : }
    1094             : 
    1095      270934 : static bool schannel_have_feature(struct gensec_security *gensec_security,
    1096             :                                          uint32_t feature)
    1097             : {
    1098      270934 :         if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
    1099      270934 :                 if (feature & GENSEC_FEATURE_SIGN) {
    1100       90421 :                         return true;
    1101             :                 }
    1102             :         }
    1103      180513 :         if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
    1104      167445 :                 if (feature & GENSEC_FEATURE_SEAL) {
    1105       72027 :                         return true;
    1106             :                 }
    1107             :         }
    1108      108486 :         if (feature & GENSEC_FEATURE_DCE_STYLE) {
    1109       69811 :                 return true;
    1110             :         }
    1111       38675 :         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1112        3103 :                 return true;
    1113             :         }
    1114       35572 :         return false;
    1115             : }
    1116             : 
    1117             : /*
    1118             :   unseal a packet
    1119             : */
    1120       23281 : static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
    1121             :                                        uint8_t *data, size_t length,
    1122             :                                        const uint8_t *whole_pdu, size_t pdu_length,
    1123             :                                        const DATA_BLOB *sig)
    1124             : {
    1125       22100 :         struct schannel_state *state =
    1126       23281 :                 talloc_get_type_abort(gensec_security->private_data,
    1127             :                 struct schannel_state);
    1128             : 
    1129       23281 :         return netsec_incoming_packet(state, true,
    1130             :                                       discard_const_p(uint8_t, data),
    1131             :                                       length,
    1132             :                                       whole_pdu, pdu_length,
    1133             :                                       sig);
    1134             : }
    1135             : 
    1136             : /*
    1137             :   check the signature on a packet
    1138             : */
    1139        5688 : static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
    1140             :                                       const uint8_t *data, size_t length,
    1141             :                                       const uint8_t *whole_pdu, size_t pdu_length,
    1142             :                                       const DATA_BLOB *sig)
    1143             : {
    1144        5688 :         struct schannel_state *state =
    1145        5688 :                 talloc_get_type_abort(gensec_security->private_data,
    1146             :                 struct schannel_state);
    1147             : 
    1148        5688 :         return netsec_incoming_packet(state, false,
    1149             :                                       discard_const_p(uint8_t, data),
    1150             :                                       length,
    1151             :                                       whole_pdu, pdu_length,
    1152             :                                       sig);
    1153             : }
    1154             : /*
    1155             :   seal a packet
    1156             : */
    1157       23265 : static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
    1158             :                                      TALLOC_CTX *mem_ctx,
    1159             :                                      uint8_t *data, size_t length,
    1160             :                                      const uint8_t *whole_pdu, size_t pdu_length,
    1161             :                                      DATA_BLOB *sig)
    1162             : {
    1163       22092 :         struct schannel_state *state =
    1164       23265 :                 talloc_get_type_abort(gensec_security->private_data,
    1165             :                 struct schannel_state);
    1166             : 
    1167       23265 :         return netsec_outgoing_packet(state, mem_ctx, true,
    1168             :                                       data, length,
    1169             :                                       whole_pdu, pdu_length,
    1170             :                                       sig);
    1171             : }
    1172             : 
    1173             : /*
    1174             :   sign a packet
    1175             : */
    1176        5688 : static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
    1177             :                                      TALLOC_CTX *mem_ctx,
    1178             :                                      const uint8_t *data, size_t length,
    1179             :                                      const uint8_t *whole_pdu, size_t pdu_length,
    1180             :                                      DATA_BLOB *sig)
    1181             : {
    1182        5688 :         struct schannel_state *state =
    1183        5688 :                 talloc_get_type_abort(gensec_security->private_data,
    1184             :                 struct schannel_state);
    1185             : 
    1186        5688 :         return netsec_outgoing_packet(state, mem_ctx, false,
    1187             :                                       discard_const_p(uint8_t, data),
    1188             :                                       length,
    1189             :                                       whole_pdu, pdu_length,
    1190             :                                       sig);
    1191             : }
    1192             : 
    1193             : static const struct gensec_security_ops gensec_schannel_security_ops = {
    1194             :         .name           = "schannel",
    1195             :         .auth_type      = DCERPC_AUTH_TYPE_SCHANNEL,
    1196             :         .client_start   = schannel_client_start,
    1197             :         .server_start   = schannel_server_start,
    1198             :         .update_send    = schannel_update_send,
    1199             :         .update_recv    = schannel_update_recv,
    1200             :         .seal_packet    = schannel_seal_packet,
    1201             :         .sign_packet    = schannel_sign_packet,
    1202             :         .check_packet   = schannel_check_packet,
    1203             :         .unseal_packet  = schannel_unseal_packet,
    1204             :         .session_info   = schannel_session_info,
    1205             :         .sig_size       = schannel_sig_size,
    1206             :         .have_feature   = schannel_have_feature,
    1207             :         .enabled        = true,
    1208             :         .priority       = GENSEC_SCHANNEL
    1209             : };
    1210             : 
    1211       10467 : _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
    1212             : {
    1213             :         NTSTATUS ret;
    1214       10467 :         ret = gensec_register(ctx, &gensec_schannel_security_ops);
    1215       10467 :         if (!NT_STATUS_IS_OK(ret)) {
    1216           0 :                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
    1217             :                         gensec_schannel_security_ops.name));
    1218           0 :                 return ret;
    1219             :         }
    1220             : 
    1221       10467 :         return ret;
    1222             : }

Generated by: LCOV version 1.13