1f8680743e9825b575e57ff8d98985a7af5a4561
[samba.git] / auth / gensec / schannel.c
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 static struct schannel_state *netsec_create_state(
65                                 struct gensec_security *gensec,
66                                 struct netlogon_creds_CredentialState *creds,
67                                 bool initiator)
68 {
69         struct schannel_state *state;
70
71         state = talloc_zero(gensec, struct schannel_state);
72         if (state == NULL) {
73                 return NULL;
74         }
75
76         state->gensec = gensec;
77         state->initiator = initiator;
78         state->creds = netlogon_creds_copy(state, creds);
79         if (state->creds == NULL) {
80                 talloc_free(state);
81                 return NULL;
82         }
83
84         gensec->private_data = state;
85
86         return state;
87 }
88
89 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         uint32_t min_sig_size;
97         uint32_t used_sig_size;
98         uint32_t checksum_length;
99         uint32_t confounder_ofs;
100
101         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
102                 min_sig_size = 48;
103                 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                 checksum_length = 8;
111                 confounder_ofs = 24;
112         } else {
113                 min_sig_size = 24;
114                 used_sig_size = 32;
115                 checksum_length = 8;
116                 confounder_ofs = 24;
117         }
118
119         if (do_seal) {
120                 min_sig_size += 8;
121         }
122
123         if (_min_sig_size) {
124                 *_min_sig_size = min_sig_size;
125         }
126
127         if (_used_sig_size) {
128                 *_used_sig_size = used_sig_size;
129         }
130
131         if (_checksum_length) {
132                 *_checksum_length = checksum_length;
133         }
134
135         if (_confounder_ofs) {
136                 *_confounder_ofs = confounder_ofs;
137         }
138 }
139
140 /*******************************************************************
141  Encode or Decode the sequence number (which is symmetric)
142  ********************************************************************/
143 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         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
149                 gnutls_cipher_hd_t cipher_hnd = NULL;
150                 gnutls_datum_t key = {
151                         .data = state->creds->session_key,
152                         .size = sizeof(state->creds->session_key),
153                 };
154                 uint32_t iv_size =
155                         gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
156                 uint8_t _iv[iv_size];
157                 gnutls_datum_t iv = {
158                         .data = _iv,
159                         .size = iv_size,
160                 };
161                 int rc;
162
163                 ZERO_ARRAY(_iv);
164
165                 memcpy(iv.data + 0, checksum, 8);
166                 memcpy(iv.data + 8, checksum, 8);
167
168                 rc = gnutls_cipher_init(&cipher_hnd,
169                                         GNUTLS_CIPHER_AES_128_CFB8,
170                                         &key,
171                                         &iv);
172                 if (rc < 0) {
173                         return gnutls_error_to_ntstatus(rc,
174                                                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
175                 }
176
177                 rc = gnutls_cipher_encrypt(cipher_hnd, seq_num, 8);
178                 gnutls_cipher_deinit(cipher_hnd);
179                 if (rc < 0) {
180                         return gnutls_error_to_ntstatus(rc,
181                                                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
182                 }
183
184         } else {
185                 static const uint8_t zeros[4];
186                 uint8_t _sequence_key[16];
187                 gnutls_cipher_hd_t cipher_hnd;
188                 gnutls_datum_t sequence_key = {
189                         .data = _sequence_key,
190                         .size = sizeof(_sequence_key),
191                 };
192                 uint8_t digest1[16];
193                 int rc;
194
195                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
196                                       state->creds->session_key,
197                                       sizeof(state->creds->session_key),
198                                       zeros,
199                                       sizeof(zeros),
200                                       digest1);
201                 if (rc < 0) {
202                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
203                 }
204
205                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
206                                       digest1,
207                                       sizeof(digest1),
208                                       checksum,
209                                       checksum_length,
210                                       _sequence_key);
211                 if (rc < 0) {
212                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
213                 }
214
215                 ZERO_ARRAY(digest1);
216
217                 rc = gnutls_cipher_init(&cipher_hnd,
218                                         GNUTLS_CIPHER_ARCFOUR_128,
219                                         &sequence_key,
220                                         NULL);
221                 if (rc < 0) {
222                         ZERO_ARRAY(_sequence_key);
223                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
224                 }
225
226                 rc = gnutls_cipher_encrypt(cipher_hnd,
227                                            seq_num,
228                                            8);
229                 gnutls_cipher_deinit(cipher_hnd);
230                 ZERO_ARRAY(_sequence_key);
231                 if (rc < 0) {
232                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
233                 }
234         }
235
236         state->seq_num++;
237
238         return NT_STATUS_OK;
239 }
240
241 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         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
248                 gnutls_cipher_hd_t cipher_hnd = NULL;
249                 uint8_t sess_kf0[16] = {0};
250                 gnutls_datum_t key = {
251                         .data = sess_kf0,
252                         .size = sizeof(sess_kf0),
253                 };
254                 uint32_t iv_size =
255                         gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
256                 uint8_t _iv[iv_size];
257                 gnutls_datum_t iv = {
258                         .data = _iv,
259                         .size = iv_size,
260                 };
261                 uint32_t i;
262                 int rc;
263
264                 for (i = 0; i < key.size; i++) {
265                         key.data[i] = state->creds->session_key[i] ^ 0xf0;
266                 }
267
268                 ZERO_ARRAY(_iv);
269
270                 memcpy(iv.data + 0, seq_num, 8);
271                 memcpy(iv.data + 8, seq_num, 8);
272
273                 rc = gnutls_cipher_init(&cipher_hnd,
274                                         GNUTLS_CIPHER_AES_128_CFB8,
275                                         &key,
276                                         &iv);
277                 if (rc < 0) {
278                         DBG_ERR("ERROR: gnutls_cipher_init: %s\n",
279                                 gnutls_strerror(rc));
280                         return NT_STATUS_NO_MEMORY;
281                 }
282
283                 if (forward) {
284                         rc = gnutls_cipher_encrypt(cipher_hnd,
285                                                    confounder,
286                                                    8);
287                         if (rc < 0) {
288                                 gnutls_cipher_deinit(cipher_hnd);
289                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
290                         }
291
292                         rc = gnutls_cipher_encrypt(cipher_hnd,
293                                                    data,
294                                                    length);
295                         if (rc < 0) {
296                                 gnutls_cipher_deinit(cipher_hnd);
297                                 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                         uint8_t tmp[16] = { 0, };
311                         uint32_t tmp_dlength = MIN(length, sizeof(tmp) - 8);
312
313                         memcpy(tmp, confounder, 8);
314                         memcpy(tmp + 8, data, tmp_dlength);
315
316                         rc = gnutls_cipher_decrypt(cipher_hnd,
317                                                    tmp,
318                                                    8 + tmp_dlength);
319                         if (rc < 0) {
320                                 ZERO_STRUCT(tmp);
321                                 gnutls_cipher_deinit(cipher_hnd);
322                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
323                         }
324
325                         memcpy(confounder, tmp, 8);
326                         memcpy(data, tmp + 8, tmp_dlength);
327                         ZERO_STRUCT(tmp);
328
329                         if (length > tmp_dlength) {
330                                 rc = gnutls_cipher_decrypt(cipher_hnd,
331                                                            data + tmp_dlength,
332                                                            length - tmp_dlength);
333                                 if (rc < 0) {
334                                         gnutls_cipher_deinit(cipher_hnd);
335                                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
336                                 }
337                         }
338                 }
339                 gnutls_cipher_deinit(cipher_hnd);
340         } else {
341                 gnutls_cipher_hd_t cipher_hnd;
342                 uint8_t _sealing_key[16];
343                 gnutls_datum_t sealing_key = {
344                         .data = _sealing_key,
345                         .size = sizeof(_sealing_key),
346                 };
347                 static const uint8_t zeros[4];
348                 uint8_t digest2[16];
349                 uint8_t sess_kf0[16];
350                 int rc;
351                 int i;
352
353                 for (i = 0; i < 16; i++) {
354                         sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
355                 }
356
357                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
358                                       sess_kf0,
359                                       sizeof(sess_kf0),
360                                       zeros,
361                                       4,
362                                       digest2);
363                 if (rc < 0) {
364                         ZERO_ARRAY(digest2);
365                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
366                 }
367
368                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
369                                       digest2,
370                                       sizeof(digest2),
371                                       seq_num,
372                                       8,
373                                       _sealing_key);
374
375                 ZERO_ARRAY(digest2);
376                 if (rc < 0) {
377                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
378                 }
379
380                 rc = gnutls_cipher_init(&cipher_hnd,
381                                         GNUTLS_CIPHER_ARCFOUR_128,
382                                         &sealing_key,
383                                         NULL);
384                 if (rc < 0) {
385                         ZERO_ARRAY(_sealing_key);
386                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
387                 }
388                 rc = gnutls_cipher_encrypt(cipher_hnd,
389                                            confounder,
390                                            8);
391                 if (rc < 0) {
392                         ZERO_ARRAY(_sealing_key);
393                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
394                 }
395                 gnutls_cipher_deinit(cipher_hnd);
396                 rc = gnutls_cipher_init(&cipher_hnd,
397                                         GNUTLS_CIPHER_ARCFOUR_128,
398                                         &sealing_key,
399                                         NULL);
400                 if (rc < 0) {
401                         ZERO_ARRAY(_sealing_key);
402                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
403                 }
404                 rc = gnutls_cipher_encrypt(cipher_hnd,
405                                            data,
406                                            length);
407                 gnutls_cipher_deinit(cipher_hnd);
408                 ZERO_ARRAY(_sealing_key);
409                 if (rc < 0) {
410                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
411                 }
412         }
413
414         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 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         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
428                 gnutls_hmac_hd_t hmac_hnd = NULL;
429                 int rc;
430
431                 rc = gnutls_hmac_init(&hmac_hnd,
432                                       GNUTLS_MAC_SHA256,
433                                       state->creds->session_key,
434                                       sizeof(state->creds->session_key));
435                 if (rc < 0) {
436                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
437                 }
438
439                 if (confounder) {
440                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
441                         SSVAL(header, 2, NL_SEAL_AES128);
442                         SSVAL(header, 4, 0xFFFF);
443                         SSVAL(header, 6, 0x0000);
444
445                         rc = gnutls_hmac(hmac_hnd, header, 8);
446                         if (rc < 0) {
447                                 gnutls_hmac_deinit(hmac_hnd, NULL);
448                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
449                         }
450                         rc = gnutls_hmac(hmac_hnd, confounder, 8);
451                         if (rc < 0) {
452                                 gnutls_hmac_deinit(hmac_hnd, NULL);
453                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
454                         }
455                 } else {
456                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
457                         SSVAL(header, 2, NL_SEAL_NONE);
458                         SSVAL(header, 4, 0xFFFF);
459                         SSVAL(header, 6, 0x0000);
460
461                         rc = gnutls_hmac(hmac_hnd, header, 8);
462                         if (rc < 0) {
463                                 gnutls_hmac_deinit(hmac_hnd, NULL);
464                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
465                         }
466                 }
467
468                 rc = gnutls_hmac(hmac_hnd, data, length);
469                 if (rc < 0) {
470                         gnutls_hmac_deinit(hmac_hnd, NULL);
471                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
472                 }
473
474                 gnutls_hmac_deinit(hmac_hnd, checksum);
475         } else {
476                 uint8_t packet_digest[16];
477                 static const uint8_t zeros[4];
478                 gnutls_hash_hd_t hash_hnd = NULL;
479                 int rc;
480
481                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
482                 if (rc < 0) {
483                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
484                 }
485
486                 rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
487                 if (rc < 0) {
488                         gnutls_hash_deinit(hash_hnd, NULL);
489                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
490                 }
491                 if (confounder) {
492                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
493                         SSVAL(header, 2, NL_SEAL_RC4);
494                         SSVAL(header, 4, 0xFFFF);
495                         SSVAL(header, 6, 0x0000);
496
497                         rc = gnutls_hash(hash_hnd, header, 8);
498                         if (rc < 0) {
499                                 gnutls_hash_deinit(hash_hnd, NULL);
500                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
501                         }
502                         rc = gnutls_hash(hash_hnd, confounder, 8);
503                         if (rc < 0) {
504                                 gnutls_hash_deinit(hash_hnd, NULL);
505                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
506                         }
507                 } else {
508                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
509                         SSVAL(header, 2, NL_SEAL_NONE);
510                         SSVAL(header, 4, 0xFFFF);
511                         SSVAL(header, 6, 0x0000);
512
513                         rc = gnutls_hash(hash_hnd, header, 8);
514                         if (rc < 0) {
515                                 gnutls_hash_deinit(hash_hnd, NULL);
516                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
517                         }
518                 }
519                 rc = gnutls_hash(hash_hnd, data, length);
520                 if (rc < 0) {
521                         gnutls_hash_deinit(hash_hnd, NULL);
522                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
523                 }
524                 gnutls_hash_deinit(hash_hnd, packet_digest);
525
526                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
527                                       state->creds->session_key,
528                                       sizeof(state->creds->session_key),
529                                       packet_digest,
530                                       sizeof(packet_digest),
531                                       checksum);
532                 ZERO_ARRAY(packet_digest);
533                 if (rc < 0) {
534                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
535                 }
536         }
537
538         return NT_STATUS_OK;
539 }
540
541 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         uint32_t min_sig_size = 0;
548         uint8_t header[8];
549         uint8_t checksum[32];
550         uint32_t checksum_length = sizeof(checksum_length);
551         uint8_t _confounder[8];
552         uint8_t *confounder = NULL;
553         uint32_t confounder_ofs = 0;
554         uint8_t seq_num[8];
555         bool ret;
556         const uint8_t *sign_data = NULL;
557         size_t sign_length = 0;
558         NTSTATUS status;
559
560         netsec_offset_and_sizes(state,
561                                 do_unseal,
562                                 &min_sig_size,
563                                 NULL,
564                                 &checksum_length,
565                                 &confounder_ofs);
566
567         if (sig->length < min_sig_size) {
568                 return NT_STATUS_ACCESS_DENIED;
569         }
570
571         if (do_unseal) {
572                 confounder = _confounder;
573                 memcpy(confounder, sig->data+confounder_ofs, 8);
574         } else {
575                 confounder = NULL;
576         }
577
578         SETUP_SEQNUM(state, seq_num, !state->initiator);
579
580         if (do_unseal) {
581                 status = netsec_do_seal(state,
582                                         seq_num,
583                                         confounder,
584                                         data,
585                                         length,
586                                         false);
587                 if (!NT_STATUS_IS_OK(status)) {
588                         DBG_WARNING("netsec_do_seal failed: %s\n", nt_errstr(status));
589                         return NT_STATUS_ACCESS_DENIED;
590                 }
591         }
592
593         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
594                 sign_data = whole_pdu;
595                 sign_length = pdu_length;
596         } else {
597                 sign_data = data;
598                 sign_length = length;
599         }
600
601         status = netsec_do_sign(state,
602                                 confounder,
603                                 sign_data,
604                                 sign_length,
605                                 header,
606                                 checksum);
607         if (!NT_STATUS_IS_OK(status)) {
608                 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
609                 return NT_STATUS_ACCESS_DENIED;
610         }
611
612         ret = mem_equal_const_time(checksum, sig->data+16, checksum_length);
613         if (!ret) {
614                 dump_data_pw("calc digest:", checksum, checksum_length);
615                 dump_data_pw("wire digest:", sig->data+16, checksum_length);
616                 return NT_STATUS_ACCESS_DENIED;
617         }
618
619         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
620         if (!NT_STATUS_IS_OK(status)) {
621                 DBG_WARNING("netsec_do_seq_num failed: %s\n",
622                             nt_errstr(status));
623                 return status;
624         }
625
626         ZERO_ARRAY(checksum);
627
628         ret = mem_equal_const_time(seq_num, sig->data+8, 8);
629         if (!ret) {
630                 dump_data_pw("calc seq num:", seq_num, 8);
631                 dump_data_pw("wire seq num:", sig->data+8, 8);
632                 return NT_STATUS_ACCESS_DENIED;
633         }
634
635         return NT_STATUS_OK;
636 }
637
638 static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
639 {
640         uint32_t sig_size = 0;
641
642         netsec_offset_and_sizes(state,
643                                 true,
644                                 NULL,
645                                 &sig_size,
646                                 NULL,
647                                 NULL);
648
649         return sig_size;
650 }
651
652 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         uint32_t min_sig_size = 0;
660         uint32_t used_sig_size = 0;
661         uint8_t header[8];
662         uint8_t checksum[32];
663         uint32_t checksum_length = sizeof(checksum_length);
664         uint8_t _confounder[8];
665         uint8_t *confounder = NULL;
666         uint32_t confounder_ofs = 0;
667         uint8_t seq_num[8];
668         const uint8_t *sign_data = NULL;
669         size_t sign_length = 0;
670         NTSTATUS status;
671
672         netsec_offset_and_sizes(state,
673                                 do_seal,
674                                 &min_sig_size,
675                                 &used_sig_size,
676                                 &checksum_length,
677                                 &confounder_ofs);
678
679         SETUP_SEQNUM(state, seq_num, state->initiator);
680
681         if (do_seal) {
682                 confounder = _confounder;
683                 generate_random_buffer(confounder, 8);
684         } else {
685                 confounder = NULL;
686         }
687
688         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
689                 sign_data = whole_pdu;
690                 sign_length = pdu_length;
691         } else {
692                 sign_data = data;
693                 sign_length = length;
694         }
695
696         status = netsec_do_sign(state,
697                                 confounder,
698                                 sign_data,
699                                 sign_length,
700                                 header,
701                                 checksum);
702         if (!NT_STATUS_IS_OK(status)) {
703                 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
704                 return NT_STATUS_ACCESS_DENIED;
705         }
706
707         if (do_seal) {
708                 status = netsec_do_seal(state,
709                                         seq_num,
710                                         confounder,
711                                         data,
712                                         length,
713                                         true);
714                 if (!NT_STATUS_IS_OK(status)) {
715                         DBG_WARNING("netsec_do_seal failed: %s\n",
716                                     nt_errstr(status));
717                         return status;
718                 }
719         }
720
721         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
722         if (!NT_STATUS_IS_OK(status)) {
723                 DBG_WARNING("netsec_do_seq_num failed: %s\n",
724                             nt_errstr(status));
725                 return status;
726         }
727
728         (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
729
730         memcpy(sig->data, header, 8);
731         memcpy(sig->data+8, seq_num, 8);
732         memcpy(sig->data+16, checksum, checksum_length);
733
734         if (confounder) {
735                 memcpy(sig->data+confounder_ofs, confounder, 8);
736         }
737
738         dump_data_pw("signature:", sig->data+ 0, 8);
739         dump_data_pw("seq_num  :", sig->data+ 8, 8);
740         dump_data_pw("digest   :", sig->data+16, checksum_length);
741         dump_data_pw("confound :", sig->data+confounder_ofs, 8);
742
743         return NT_STATUS_OK;
744 }
745
746 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
747
748 static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
749 {
750         struct schannel_state *state =
751                 talloc_get_type_abort(gensec_security->private_data,
752                 struct schannel_state);
753
754         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 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         struct tevent_req *req;
772         struct schannel_update_state *state = NULL;
773         NTSTATUS status;
774
775         req = tevent_req_create(mem_ctx, &state,
776                                 struct schannel_update_state);
777         if (req == NULL) {
778                 return NULL;
779         }
780
781         status = schannel_update_internal(gensec_security,
782                                           state, in,
783                                           &state->out);
784         state->status = status;
785         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
786                 status = NT_STATUS_OK;
787         }
788         if (tevent_req_nterror(req, status)) {
789                 return tevent_req_post(req, ev);
790         }
791
792         tevent_req_done(req);
793         return tevent_req_post(req, ev);
794 }
795
796 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         struct schannel_state *state =
801                 talloc_get_type(gensec_security->private_data,
802                 struct schannel_state);
803         NTSTATUS status;
804         enum ndr_err_code ndr_err;
805         struct NL_AUTH_MESSAGE bind_schannel = {
806                 .Flags = 0,
807         };
808         struct NL_AUTH_MESSAGE bind_schannel_ack;
809         struct netlogon_creds_CredentialState *creds;
810         const char *workstation;
811         const char *domain;
812
813         *out = data_blob(NULL, 0);
814
815         if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
816                 switch (gensec_security->gensec_role) {
817                 case GENSEC_CLIENT:
818                         return NT_STATUS_INVALID_PARAMETER_MIX;
819                 case GENSEC_SERVER:
820                         return NT_STATUS_INVALID_PARAMETER;
821                 }
822                 return NT_STATUS_INTERNAL_ERROR;
823         }
824
825         switch (gensec_security->gensec_role) {
826         case GENSEC_CLIENT:
827                 if (state != NULL) {
828                         /* we could parse the bind ack, but we don't know what it is yet */
829                         return NT_STATUS_OK;
830                 }
831
832                 creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
833                 if (creds == NULL) {
834                         return NT_STATUS_INVALID_PARAMETER_MIX;
835                 }
836
837                 state = netsec_create_state(gensec_security,
838                                             creds, true /* initiator */);
839                 if (state == NULL) {
840                         return NT_STATUS_NO_MEMORY;
841                 }
842
843                 bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
844
845                 bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
846                                       NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
847                 bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
848                 bind_schannel.oem_netbios_computer.a = creds->computer_name;
849
850                 if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
851                         bind_schannel.Flags |= NL_FLAG_UTF8_DNS_DOMAIN_NAME;
852                         bind_schannel.utf8_dns_domain.u = cli_credentials_get_realm(gensec_security->credentials);
853
854                         bind_schannel.Flags |= NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME;
855                         bind_schannel.utf8_netbios_computer.u = creds->computer_name;
856                 }
857
858                 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
859                                                (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
860                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
861                         status = ndr_map_error2ntstatus(ndr_err);
862                         DEBUG(3, ("Could not create schannel bind: %s\n",
863                                   nt_errstr(status)));
864                         return status;
865                 }
866
867                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
868         case GENSEC_SERVER:
869
870                 if (state != NULL) {
871                         /* no third leg on this protocol */
872                         return NT_STATUS_INVALID_PARAMETER;
873                 }
874
875                 /* parse the schannel startup blob */
876                 ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
877                         (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
878                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
879                         status = ndr_map_error2ntstatus(ndr_err);
880                         DEBUG(3, ("Could not parse incoming schannel bind: %s\n",
881                                   nt_errstr(status)));
882                         return status;
883                 }
884
885                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
886                         domain = bind_schannel.oem_netbios_domain.a;
887                         if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) {
888                                 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
889                                           domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)));
890                                 return NT_STATUS_LOGON_FAILURE;
891                         }
892                 } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) {
893                         domain = bind_schannel.utf8_dns_domain.u;
894                         if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) {
895                                 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
896                                           domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)));
897                                 return NT_STATUS_LOGON_FAILURE;
898                         }
899                 } else {
900                         DEBUG(3, ("Request for schannel to without domain\n"));
901                         return NT_STATUS_LOGON_FAILURE;
902                 }
903
904                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
905                         workstation = bind_schannel.oem_netbios_computer.a;
906                 } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) {
907                         workstation = bind_schannel.utf8_netbios_computer.u;
908                 } else {
909                         DEBUG(3, ("Request for schannel to without netbios workstation\n"));
910                         return NT_STATUS_LOGON_FAILURE;
911                 }
912
913                 status = schannel_get_creds_state(out_mem_ctx,
914                                                   gensec_security->settings->lp_ctx,
915                                                   workstation, &creds);
916                 if (!NT_STATUS_IS_OK(status)) {
917                         DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
918                                   workstation, nt_errstr(status)));
919                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
920                                 return NT_STATUS_LOGON_FAILURE;
921                         }
922                         return status;
923                 }
924
925                 state = netsec_create_state(gensec_security,
926                                             creds, false /* not initiator */);
927                 if (state == NULL) {
928                         return NT_STATUS_NO_MEMORY;
929                 }
930
931                 status = auth_anonymous_user_info_dc(state,
932                                 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
933                                 &state->user_info_dc);
934                 if (!NT_STATUS_IS_OK(status)) {
935                         return status;
936                 }
937
938                 bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
939                 bind_schannel_ack.Flags = 0;
940                 bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
941                                                             * this does not have
942                                                             * any meaning here
943                                                             * - gd */
944
945                 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                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
948                         status = ndr_map_error2ntstatus(ndr_err);
949                         DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
950                                   workstation, nt_errstr(status)));
951                         return status;
952                 }
953
954                 return NT_STATUS_OK;
955         }
956         return NT_STATUS_INVALID_PARAMETER;
957 }
958
959 static NTSTATUS schannel_update_recv(struct tevent_req *req,
960                                      TALLOC_CTX *out_mem_ctx,
961                                      DATA_BLOB *out)
962 {
963         struct schannel_update_state *state =
964                 tevent_req_data(req,
965                 struct schannel_update_state);
966         NTSTATUS status;
967
968         *out = data_blob_null;
969
970         if (tevent_req_is_nterror(req, &status)) {
971                 tevent_req_received(req);
972                 return status;
973         }
974
975         status = state->status;
976         talloc_steal(out_mem_ctx, state->out.data);
977         *out = state->out;
978         tevent_req_received(req);
979         return status;
980 }
981
982 /**
983  * Returns anonymous credentials for schannel, matching Win2k3.
984  *
985  */
986
987 static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
988                                       TALLOC_CTX *mem_ctx,
989                                       struct auth_session_info **_session_info)
990 {
991         struct schannel_state *state =
992                 talloc_get_type(gensec_security->private_data,
993                 struct schannel_state);
994         struct auth4_context *auth_ctx = gensec_security->auth_context;
995         struct auth_session_info *session_info = NULL;
996         uint32_t session_info_flags = 0;
997         NTSTATUS status;
998
999         if (auth_ctx == NULL) {
1000                 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
1001                 return NT_STATUS_INTERNAL_ERROR;
1002         }
1003
1004         if (auth_ctx->generate_session_info == NULL) {
1005                 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
1006                 return NT_STATUS_INTERNAL_ERROR;
1007         }
1008
1009         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
1010                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1011         }
1012
1013         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1014
1015         status = auth_ctx->generate_session_info(
1016                                 auth_ctx,
1017                                 mem_ctx,
1018                                 state->user_info_dc,
1019                                 state->user_info_dc->info->account_name,
1020                                 session_info_flags,
1021                                 &session_info);
1022         if (!NT_STATUS_IS_OK(status)) {
1023                 return status;
1024         }
1025
1026         *_session_info = session_info;
1027         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 static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
1035 {
1036         enum server_role server_role
1037                 = lpcfg_server_role(gensec_security->settings->lp_ctx);
1038
1039         switch (server_role) {
1040         case ROLE_DOMAIN_BDC:
1041         case ROLE_DOMAIN_PDC:
1042         case ROLE_ACTIVE_DIRECTORY_DC:
1043         case ROLE_IPA_DC:
1044                 return NT_STATUS_OK;
1045         default:
1046                 return NT_STATUS_NOT_IMPLEMENTED;
1047         }
1048 }
1049
1050 static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
1051 {
1052         return NT_STATUS_OK;
1053 }
1054
1055 static bool schannel_have_feature(struct gensec_security *gensec_security,
1056                                          uint32_t feature)
1057 {
1058         if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1059                 if (feature & GENSEC_FEATURE_SIGN) {
1060                         return true;
1061                 }
1062         }
1063         if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
1064                 if (feature & GENSEC_FEATURE_SEAL) {
1065                         return true;
1066                 }
1067         }
1068         if (feature & GENSEC_FEATURE_DCE_STYLE) {
1069                 return true;
1070         }
1071         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1072                 return true;
1073         }
1074         return false;
1075 }
1076
1077 /*
1078   unseal a packet
1079 */
1080 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         struct schannel_state *state =
1086                 talloc_get_type_abort(gensec_security->private_data,
1087                 struct schannel_state);
1088
1089         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 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         struct schannel_state *state =
1105                 talloc_get_type_abort(gensec_security->private_data,
1106                 struct schannel_state);
1107
1108         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 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         struct schannel_state *state =
1124                 talloc_get_type_abort(gensec_security->private_data,
1125                 struct schannel_state);
1126
1127         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 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         struct schannel_state *state =
1143                 talloc_get_type_abort(gensec_security->private_data,
1144                 struct schannel_state);
1145
1146         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 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
1172 {
1173         NTSTATUS ret;
1174         ret = gensec_register(ctx, &gensec_schannel_security_ops);
1175         if (!NT_STATUS_IS_OK(ret)) {
1176                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1177                         gensec_schannel_security_ops.name));
1178                 return ret;
1179         }
1180
1181         return ret;
1182 }