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