LCOV - code coverage report
Current view: top level - auth/gensec - schannel.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 421 544 77.4 %
Date: 2023-11-21 12:31:41 Functions: 21 21 100.0 %

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

Generated by: LCOV version 1.14