18e2ed6cd366c90fef34413d3eb0f01958e22acb
[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                                 DBG_ERR("ERROR: gnutls_cipher_encrypt: %s\n",
306                                         gnutls_strerror(errno));
307                                 gnutls_cipher_deinit(cipher_hnd);
308                                 return NT_STATUS_INTERNAL_ERROR;
309                         }
310
311                         /*
312                          * Looks like we have to reuse the initial IV which is
313                          * cryptographically wrong!
314                          */
315                         gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size);
316                         rc = gnutls_cipher_encrypt(cipher_hnd,
317                                                    data,
318                                                    length);
319                         if (rc < 0) {
320                                 DBG_ERR("ERROR: gnutls_cipher_encrypt: %s\n",
321                                         gnutls_strerror(errno));
322                                 gnutls_cipher_deinit(cipher_hnd);
323                                 return NT_STATUS_INTERNAL_ERROR;
324                         }
325                 } else {
326                         rc = gnutls_cipher_decrypt(cipher_hnd,
327                                                    confounder,
328                                                    8);
329                         if (rc < 0) {
330                                 DBG_ERR("ERROR: gnutls_cipher_decrypt: %s\n",
331                                         gnutls_strerror(errno));
332                                 gnutls_cipher_deinit(cipher_hnd);
333                                 return NT_STATUS_INTERNAL_ERROR;
334                         }
335
336                         /*
337                          * Looks like we have to reuse the initial IV which is
338                          * cryptographically wrong!
339                          */
340                         gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size);
341                         rc = gnutls_cipher_decrypt(cipher_hnd,
342                                                    data,
343                                                    length);
344                         if (rc < 0) {
345                                 DBG_ERR("ERROR: gnutls_cipher_decrypt: %s\n",
346                                         gnutls_strerror(errno));
347                                 gnutls_cipher_deinit(cipher_hnd);
348                                 return NT_STATUS_INTERNAL_ERROR;
349                         }
350                 }
351                 gnutls_cipher_deinit(cipher_hnd);
352 #else /* NOT HAVE_GNUTLS_AES_CFB8 */
353                 AES_KEY key;
354                 uint8_t iv[AES_BLOCK_SIZE];
355                 uint8_t sess_kf0[16];
356                 int i;
357
358                 for (i = 0; i < 16; i++) {
359                         sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
360                 }
361
362                 AES_set_encrypt_key(sess_kf0, 128, &key);
363                 ZERO_STRUCT(iv);
364                 memcpy(iv+0, seq_num, 8);
365                 memcpy(iv+8, seq_num, 8);
366
367                 if (forward) {
368                         aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT);
369                         aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT);
370                 } else {
371                         aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT);
372                         aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT);
373                 }
374 #endif /* HAVE_GNUTLS_AES_CFB8 */
375         } else {
376                 gnutls_cipher_hd_t cipher_hnd;
377                 uint8_t _sealing_key[16];
378                 gnutls_datum_t sealing_key = {
379                         .data = _sealing_key,
380                         .size = sizeof(_sealing_key),
381                 };
382                 static const uint8_t zeros[4];
383                 uint8_t digest2[16];
384                 uint8_t sess_kf0[16];
385                 int rc;
386                 int i;
387
388                 for (i = 0; i < 16; i++) {
389                         sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
390                 }
391
392                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
393                                       sess_kf0,
394                                       sizeof(sess_kf0),
395                                       zeros,
396                                       4,
397                                       digest2);
398                 if (rc < 0) {
399                         ZERO_ARRAY(digest2);
400                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
401                 }
402
403                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
404                                       digest2,
405                                       sizeof(digest2),
406                                       seq_num,
407                                       8,
408                                       _sealing_key);
409
410                 ZERO_ARRAY(digest2);
411                 if (rc < 0) {
412                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
413                 }
414
415                 rc = gnutls_cipher_init(&cipher_hnd,
416                                         GNUTLS_CIPHER_ARCFOUR_128,
417                                         &sealing_key,
418                                         NULL);
419                 if (rc < 0) {
420                         ZERO_ARRAY(_sealing_key);
421                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
422                 }
423                 rc = gnutls_cipher_encrypt(cipher_hnd,
424                                            confounder,
425                                            8);
426                 if (rc < 0) {
427                         ZERO_ARRAY(_sealing_key);
428                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
429                 }
430                 rc = gnutls_cipher_encrypt(cipher_hnd,
431                                            data,
432                                            length);
433                 gnutls_cipher_deinit(cipher_hnd);
434                 ZERO_ARRAY(_sealing_key);
435                 if (rc < 0) {
436                         return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
437                 }
438         }
439
440         return NT_STATUS_OK;
441 }
442
443 /*******************************************************************
444  Create a digest over the entire packet (including the data), and
445  MD5 it with the session key.
446  ********************************************************************/
447 static NTSTATUS netsec_do_sign(struct schannel_state *state,
448                                const uint8_t *confounder,
449                                const uint8_t *data, size_t length,
450                                uint8_t header[8],
451                                uint8_t *checksum)
452 {
453         if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
454                 gnutls_hmac_hd_t hmac_hnd = NULL;
455                 int rc;
456
457                 rc = gnutls_hmac_init(&hmac_hnd,
458                                       GNUTLS_MAC_SHA256,
459                                       state->creds->session_key,
460                                       sizeof(state->creds->session_key));
461                 if (rc < 0) {
462                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
463                 }
464
465                 if (confounder) {
466                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
467                         SSVAL(header, 2, NL_SEAL_AES128);
468                         SSVAL(header, 4, 0xFFFF);
469                         SSVAL(header, 6, 0x0000);
470
471                         rc = gnutls_hmac(hmac_hnd, header, 8);
472                         if (rc < 0) {
473                                 gnutls_hmac_deinit(hmac_hnd, NULL);
474                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
475                         }
476                         rc = gnutls_hmac(hmac_hnd, confounder, 8);
477                         if (rc < 0) {
478                                 gnutls_hmac_deinit(hmac_hnd, NULL);
479                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
480                         }
481                 } else {
482                         SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
483                         SSVAL(header, 2, NL_SEAL_NONE);
484                         SSVAL(header, 4, 0xFFFF);
485                         SSVAL(header, 6, 0x0000);
486
487                         rc = gnutls_hmac(hmac_hnd, header, 8);
488                         if (rc < 0) {
489                                 gnutls_hmac_deinit(hmac_hnd, NULL);
490                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
491                         }
492                 }
493
494                 rc = gnutls_hmac(hmac_hnd, data, length);
495                 if (rc < 0) {
496                         gnutls_hmac_deinit(hmac_hnd, NULL);
497                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
498                 }
499
500                 gnutls_hmac_deinit(hmac_hnd, checksum);
501         } else {
502                 uint8_t packet_digest[16];
503                 static const uint8_t zeros[4];
504                 gnutls_hash_hd_t hash_hnd = NULL;
505                 int rc;
506
507                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
508                 if (rc < 0) {
509                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
510                 }
511
512                 rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
513                 if (rc < 0) {
514                         gnutls_hash_deinit(hash_hnd, NULL);
515                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
516                 }
517                 if (confounder) {
518                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
519                         SSVAL(header, 2, NL_SEAL_RC4);
520                         SSVAL(header, 4, 0xFFFF);
521                         SSVAL(header, 6, 0x0000);
522
523                         rc = gnutls_hash(hash_hnd, header, 8);
524                         if (rc < 0) {
525                                 gnutls_hash_deinit(hash_hnd, NULL);
526                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
527                         }
528                         rc = gnutls_hash(hash_hnd, confounder, 8);
529                         if (rc < 0) {
530                                 gnutls_hash_deinit(hash_hnd, NULL);
531                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
532                         }
533                 } else {
534                         SSVAL(header, 0, NL_SIGN_HMAC_MD5);
535                         SSVAL(header, 2, NL_SEAL_NONE);
536                         SSVAL(header, 4, 0xFFFF);
537                         SSVAL(header, 6, 0x0000);
538
539                         rc = gnutls_hash(hash_hnd, header, 8);
540                         if (rc < 0) {
541                                 gnutls_hash_deinit(hash_hnd, NULL);
542                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
543                         }
544                 }
545                 rc = gnutls_hash(hash_hnd, data, length);
546                 if (rc < 0) {
547                         gnutls_hash_deinit(hash_hnd, NULL);
548                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
549                 }
550                 gnutls_hash_deinit(hash_hnd, packet_digest);
551
552                 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
553                                       state->creds->session_key,
554                                       sizeof(state->creds->session_key),
555                                       packet_digest,
556                                       sizeof(packet_digest),
557                                       checksum);
558                 ZERO_ARRAY(packet_digest);
559                 if (rc < 0) {
560                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
561                 }
562         }
563
564         return NT_STATUS_OK;
565 }
566
567 static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
568                                 bool do_unseal,
569                                 uint8_t *data, size_t length,
570                                 const uint8_t *whole_pdu, size_t pdu_length,
571                                 const DATA_BLOB *sig)
572 {
573         uint32_t min_sig_size = 0;
574         uint8_t header[8];
575         uint8_t checksum[32];
576         uint32_t checksum_length = sizeof(checksum_length);
577         uint8_t _confounder[8];
578         uint8_t *confounder = NULL;
579         uint32_t confounder_ofs = 0;
580         uint8_t seq_num[8];
581         int ret;
582         const uint8_t *sign_data = NULL;
583         size_t sign_length = 0;
584         NTSTATUS status;
585
586         netsec_offset_and_sizes(state,
587                                 do_unseal,
588                                 &min_sig_size,
589                                 NULL,
590                                 &checksum_length,
591                                 &confounder_ofs);
592
593         if (sig->length < min_sig_size) {
594                 return NT_STATUS_ACCESS_DENIED;
595         }
596
597         if (do_unseal) {
598                 confounder = _confounder;
599                 memcpy(confounder, sig->data+confounder_ofs, 8);
600         } else {
601                 confounder = NULL;
602         }
603
604         SETUP_SEQNUM(state, seq_num, !state->initiator);
605
606         if (do_unseal) {
607                 status = netsec_do_seal(state,
608                                         seq_num,
609                                         confounder,
610                                         data,
611                                         length,
612                                         false);
613                 if (!NT_STATUS_IS_OK(status)) {
614                         DBG_WARNING("netsec_do_seal failed: %s\n", nt_errstr(status));
615                         return NT_STATUS_ACCESS_DENIED;
616                 }
617         }
618
619         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
620                 sign_data = whole_pdu;
621                 sign_length = pdu_length;
622         } else {
623                 sign_data = data;
624                 sign_length = length;
625         }
626
627         status = netsec_do_sign(state,
628                                 confounder,
629                                 sign_data,
630                                 sign_length,
631                                 header,
632                                 checksum);
633         if (!NT_STATUS_IS_OK(status)) {
634                 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
635                 return NT_STATUS_ACCESS_DENIED;
636         }
637
638         ret = memcmp(checksum, sig->data+16, checksum_length);
639         if (ret != 0) {
640                 dump_data_pw("calc digest:", checksum, checksum_length);
641                 dump_data_pw("wire digest:", sig->data+16, checksum_length);
642                 return NT_STATUS_ACCESS_DENIED;
643         }
644
645         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
646         if (!NT_STATUS_IS_OK(status)) {
647                 DBG_WARNING("netsec_do_seq_num failed: %s\n",
648                             nt_errstr(status));
649                 return status;
650         }
651
652         ZERO_ARRAY(checksum);
653
654         ret = memcmp(seq_num, sig->data+8, 8);
655         if (ret != 0) {
656                 dump_data_pw("calc seq num:", seq_num, 8);
657                 dump_data_pw("wire seq num:", sig->data+8, 8);
658                 return NT_STATUS_ACCESS_DENIED;
659         }
660
661         return NT_STATUS_OK;
662 }
663
664 static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
665 {
666         uint32_t sig_size = 0;
667
668         netsec_offset_and_sizes(state,
669                                 true,
670                                 NULL,
671                                 &sig_size,
672                                 NULL,
673                                 NULL);
674
675         return sig_size;
676 }
677
678 static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
679                                 TALLOC_CTX *mem_ctx,
680                                 bool do_seal,
681                                 uint8_t *data, size_t length,
682                                 const uint8_t *whole_pdu, size_t pdu_length,
683                                 DATA_BLOB *sig)
684 {
685         uint32_t min_sig_size = 0;
686         uint32_t used_sig_size = 0;
687         uint8_t header[8];
688         uint8_t checksum[32];
689         uint32_t checksum_length = sizeof(checksum_length);
690         uint8_t _confounder[8];
691         uint8_t *confounder = NULL;
692         uint32_t confounder_ofs = 0;
693         uint8_t seq_num[8];
694         const uint8_t *sign_data = NULL;
695         size_t sign_length = 0;
696         NTSTATUS status;
697
698         netsec_offset_and_sizes(state,
699                                 do_seal,
700                                 &min_sig_size,
701                                 &used_sig_size,
702                                 &checksum_length,
703                                 &confounder_ofs);
704
705         SETUP_SEQNUM(state, seq_num, state->initiator);
706
707         if (do_seal) {
708                 confounder = _confounder;
709                 generate_random_buffer(confounder, 8);
710         } else {
711                 confounder = NULL;
712         }
713
714         if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
715                 sign_data = whole_pdu;
716                 sign_length = pdu_length;
717         } else {
718                 sign_data = data;
719                 sign_length = length;
720         }
721
722         status = netsec_do_sign(state,
723                                 confounder,
724                                 sign_data,
725                                 sign_length,
726                                 header,
727                                 checksum);
728         if (!NT_STATUS_IS_OK(status)) {
729                 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
730                 return NT_STATUS_ACCESS_DENIED;
731         }
732
733         if (do_seal) {
734                 status = netsec_do_seal(state,
735                                         seq_num,
736                                         confounder,
737                                         data,
738                                         length,
739                                         true);
740                 if (!NT_STATUS_IS_OK(status)) {
741                         DBG_WARNING("netsec_do_seal failed: %s\n",
742                                     nt_errstr(status));
743                         return status;
744                 }
745         }
746
747         status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
748         if (!NT_STATUS_IS_OK(status)) {
749                 DBG_WARNING("netsec_do_seq_num failed: %s\n",
750                             nt_errstr(status));
751                 return status;
752         }
753
754         (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
755
756         memcpy(sig->data, header, 8);
757         memcpy(sig->data+8, seq_num, 8);
758         memcpy(sig->data+16, checksum, checksum_length);
759
760         if (confounder) {
761                 memcpy(sig->data+confounder_ofs, confounder, 8);
762         }
763
764         dump_data_pw("signature:", sig->data+ 0, 8);
765         dump_data_pw("seq_num  :", sig->data+ 8, 8);
766         dump_data_pw("digest   :", sig->data+16, checksum_length);
767         dump_data_pw("confound :", sig->data+confounder_ofs, 8);
768
769         return NT_STATUS_OK;
770 }
771
772 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
773
774 static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
775 {
776         struct schannel_state *state =
777                 talloc_get_type_abort(gensec_security->private_data,
778                 struct schannel_state);
779
780         return netsec_outgoing_sig_size(state);
781 }
782
783 struct schannel_update_state {
784         NTSTATUS status;
785         DATA_BLOB out;
786 };
787
788 static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
789                                          TALLOC_CTX *out_mem_ctx,
790                                          const DATA_BLOB in, DATA_BLOB *out);
791
792 static struct tevent_req *schannel_update_send(TALLOC_CTX *mem_ctx,
793                                                struct tevent_context *ev,
794                                                struct gensec_security *gensec_security,
795                                                const DATA_BLOB in)
796 {
797         struct tevent_req *req;
798         struct schannel_update_state *state = NULL;
799         NTSTATUS status;
800
801         req = tevent_req_create(mem_ctx, &state,
802                                 struct schannel_update_state);
803         if (req == NULL) {
804                 return NULL;
805         }
806
807         status = schannel_update_internal(gensec_security,
808                                           state, in,
809                                           &state->out);
810         state->status = status;
811         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
812                 status = NT_STATUS_OK;
813         }
814         if (tevent_req_nterror(req, status)) {
815                 return tevent_req_post(req, ev);
816         }
817
818         tevent_req_done(req);
819         return tevent_req_post(req, ev);
820 }
821
822 static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
823                                          TALLOC_CTX *out_mem_ctx,
824                                          const DATA_BLOB in, DATA_BLOB *out)
825 {
826         struct schannel_state *state =
827                 talloc_get_type(gensec_security->private_data,
828                 struct schannel_state);
829         NTSTATUS status;
830         enum ndr_err_code ndr_err;
831         struct NL_AUTH_MESSAGE bind_schannel = {
832                 .Flags = 0,
833         };
834         struct NL_AUTH_MESSAGE bind_schannel_ack;
835         struct netlogon_creds_CredentialState *creds;
836         const char *workstation;
837         const char *domain;
838
839         *out = data_blob(NULL, 0);
840
841         if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
842                 switch (gensec_security->gensec_role) {
843                 case GENSEC_CLIENT:
844                         return NT_STATUS_INVALID_PARAMETER_MIX;
845                 case GENSEC_SERVER:
846                         return NT_STATUS_INVALID_PARAMETER;
847                 }
848                 return NT_STATUS_INTERNAL_ERROR;
849         }
850
851         switch (gensec_security->gensec_role) {
852         case GENSEC_CLIENT:
853                 if (state != NULL) {
854                         /* we could parse the bind ack, but we don't know what it is yet */
855                         return NT_STATUS_OK;
856                 }
857
858                 creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
859                 if (creds == NULL) {
860                         return NT_STATUS_INVALID_PARAMETER_MIX;
861                 }
862
863                 state = netsec_create_state(gensec_security,
864                                             creds, true /* initiator */);
865                 if (state == NULL) {
866                         return NT_STATUS_NO_MEMORY;
867                 }
868
869                 bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
870
871                 bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
872                                       NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
873                 bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
874                 bind_schannel.oem_netbios_computer.a = creds->computer_name;
875
876                 if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
877                         bind_schannel.Flags |= NL_FLAG_UTF8_DNS_DOMAIN_NAME;
878                         bind_schannel.utf8_dns_domain.u = cli_credentials_get_realm(gensec_security->credentials);
879
880                         bind_schannel.Flags |= NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME;
881                         bind_schannel.utf8_netbios_computer.u = creds->computer_name;
882                 }
883
884                 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
885                                                (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
886                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
887                         status = ndr_map_error2ntstatus(ndr_err);
888                         DEBUG(3, ("Could not create schannel bind: %s\n",
889                                   nt_errstr(status)));
890                         return status;
891                 }
892
893                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
894         case GENSEC_SERVER:
895
896                 if (state != NULL) {
897                         /* no third leg on this protocol */
898                         return NT_STATUS_INVALID_PARAMETER;
899                 }
900
901                 /* parse the schannel startup blob */
902                 ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
903                         (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
904                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
905                         status = ndr_map_error2ntstatus(ndr_err);
906                         DEBUG(3, ("Could not parse incoming schannel bind: %s\n",
907                                   nt_errstr(status)));
908                         return status;
909                 }
910
911                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
912                         domain = bind_schannel.oem_netbios_domain.a;
913                         if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) {
914                                 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
915                                           domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)));
916                                 return NT_STATUS_LOGON_FAILURE;
917                         }
918                 } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) {
919                         domain = bind_schannel.utf8_dns_domain.u;
920                         if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) {
921                                 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
922                                           domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)));
923                                 return NT_STATUS_LOGON_FAILURE;
924                         }
925                 } else {
926                         DEBUG(3, ("Request for schannel to without domain\n"));
927                         return NT_STATUS_LOGON_FAILURE;
928                 }
929
930                 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
931                         workstation = bind_schannel.oem_netbios_computer.a;
932                 } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) {
933                         workstation = bind_schannel.utf8_netbios_computer.u;
934                 } else {
935                         DEBUG(3, ("Request for schannel to without netbios workstation\n"));
936                         return NT_STATUS_LOGON_FAILURE;
937                 }
938
939                 status = schannel_get_creds_state(out_mem_ctx,
940                                                   gensec_security->settings->lp_ctx,
941                                                   workstation, &creds);
942                 if (!NT_STATUS_IS_OK(status)) {
943                         DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
944                                   workstation, nt_errstr(status)));
945                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
946                                 return NT_STATUS_LOGON_FAILURE;
947                         }
948                         return status;
949                 }
950
951                 state = netsec_create_state(gensec_security,
952                                             creds, false /* not initiator */);
953                 if (state == NULL) {
954                         return NT_STATUS_NO_MEMORY;
955                 }
956
957                 status = auth_anonymous_user_info_dc(state,
958                                 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
959                                 &state->user_info_dc);
960                 if (!NT_STATUS_IS_OK(status)) {
961                         return status;
962                 }
963
964                 bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
965                 bind_schannel_ack.Flags = 0;
966                 bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
967                                                             * this does not have
968                                                             * any meaning here
969                                                             * - gd */
970
971                 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack,
972                                                (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
973                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
974                         status = ndr_map_error2ntstatus(ndr_err);
975                         DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
976                                   workstation, nt_errstr(status)));
977                         return status;
978                 }
979
980                 return NT_STATUS_OK;
981         }
982         return NT_STATUS_INVALID_PARAMETER;
983 }
984
985 static NTSTATUS schannel_update_recv(struct tevent_req *req,
986                                      TALLOC_CTX *out_mem_ctx,
987                                      DATA_BLOB *out)
988 {
989         struct schannel_update_state *state =
990                 tevent_req_data(req,
991                 struct schannel_update_state);
992         NTSTATUS status;
993
994         *out = data_blob_null;
995
996         if (tevent_req_is_nterror(req, &status)) {
997                 tevent_req_received(req);
998                 return status;
999         }
1000
1001         status = state->status;
1002         talloc_steal(out_mem_ctx, state->out.data);
1003         *out = state->out;
1004         tevent_req_received(req);
1005         return status;
1006 }
1007
1008 /**
1009  * Returns anonymous credentials for schannel, matching Win2k3.
1010  *
1011  */
1012
1013 static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
1014                                       TALLOC_CTX *mem_ctx,
1015                                       struct auth_session_info **_session_info)
1016 {
1017         struct schannel_state *state =
1018                 talloc_get_type(gensec_security->private_data,
1019                 struct schannel_state);
1020         struct auth4_context *auth_ctx = gensec_security->auth_context;
1021         struct auth_session_info *session_info = NULL;
1022         uint32_t session_info_flags = 0;
1023         NTSTATUS status;
1024
1025         if (auth_ctx == NULL) {
1026                 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
1027                 return NT_STATUS_INTERNAL_ERROR;
1028         }
1029
1030         if (auth_ctx->generate_session_info == NULL) {
1031                 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
1032                 return NT_STATUS_INTERNAL_ERROR;
1033         }
1034
1035         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
1036                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1037         }
1038
1039         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1040
1041         status = auth_ctx->generate_session_info(
1042                                 auth_ctx,
1043                                 mem_ctx,
1044                                 state->user_info_dc,
1045                                 state->user_info_dc->info->account_name,
1046                                 session_info_flags,
1047                                 &session_info);
1048         if (!NT_STATUS_IS_OK(status)) {
1049                 return status;
1050         }
1051
1052         *_session_info = session_info;
1053         return NT_STATUS_OK;
1054 }
1055
1056 /*
1057  * Reduce the attack surface by ensuring schannel is not availble when
1058  * we are not a DC
1059  */
1060 static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
1061 {
1062         enum server_role server_role
1063                 = lpcfg_server_role(gensec_security->settings->lp_ctx);
1064
1065         switch (server_role) {
1066         case ROLE_DOMAIN_BDC:
1067         case ROLE_DOMAIN_PDC:
1068         case ROLE_ACTIVE_DIRECTORY_DC:
1069                 return NT_STATUS_OK;
1070         default:
1071                 return NT_STATUS_NOT_IMPLEMENTED;
1072         }
1073 }
1074
1075 static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
1076 {
1077         return NT_STATUS_OK;
1078 }
1079
1080 static bool schannel_have_feature(struct gensec_security *gensec_security,
1081                                          uint32_t feature)
1082 {
1083         if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1084                 if (feature & GENSEC_FEATURE_SIGN) {
1085                         return true;
1086                 }
1087         }
1088         if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
1089                 if (feature & GENSEC_FEATURE_SEAL) {
1090                         return true;
1091                 }
1092         }
1093         if (feature & GENSEC_FEATURE_DCE_STYLE) {
1094                 return true;
1095         }
1096         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1097                 return true;
1098         }
1099         return false;
1100 }
1101
1102 /*
1103   unseal a packet
1104 */
1105 static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
1106                                        uint8_t *data, size_t length,
1107                                        const uint8_t *whole_pdu, size_t pdu_length,
1108                                        const DATA_BLOB *sig)
1109 {
1110         struct schannel_state *state =
1111                 talloc_get_type_abort(gensec_security->private_data,
1112                 struct schannel_state);
1113
1114         return netsec_incoming_packet(state, true,
1115                                       discard_const_p(uint8_t, data),
1116                                       length,
1117                                       whole_pdu, pdu_length,
1118                                       sig);
1119 }
1120
1121 /*
1122   check the signature on a packet
1123 */
1124 static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
1125                                       const uint8_t *data, size_t length,
1126                                       const uint8_t *whole_pdu, size_t pdu_length,
1127                                       const DATA_BLOB *sig)
1128 {
1129         struct schannel_state *state =
1130                 talloc_get_type_abort(gensec_security->private_data,
1131                 struct schannel_state);
1132
1133         return netsec_incoming_packet(state, false,
1134                                       discard_const_p(uint8_t, data),
1135                                       length,
1136                                       whole_pdu, pdu_length,
1137                                       sig);
1138 }
1139 /*
1140   seal a packet
1141 */
1142 static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
1143                                      TALLOC_CTX *mem_ctx,
1144                                      uint8_t *data, size_t length,
1145                                      const uint8_t *whole_pdu, size_t pdu_length,
1146                                      DATA_BLOB *sig)
1147 {
1148         struct schannel_state *state =
1149                 talloc_get_type_abort(gensec_security->private_data,
1150                 struct schannel_state);
1151
1152         return netsec_outgoing_packet(state, mem_ctx, true,
1153                                       data, length,
1154                                       whole_pdu, pdu_length,
1155                                       sig);
1156 }
1157
1158 /*
1159   sign a packet
1160 */
1161 static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
1162                                      TALLOC_CTX *mem_ctx,
1163                                      const uint8_t *data, size_t length,
1164                                      const uint8_t *whole_pdu, size_t pdu_length,
1165                                      DATA_BLOB *sig)
1166 {
1167         struct schannel_state *state =
1168                 talloc_get_type_abort(gensec_security->private_data,
1169                 struct schannel_state);
1170
1171         return netsec_outgoing_packet(state, mem_ctx, false,
1172                                       discard_const_p(uint8_t, data),
1173                                       length,
1174                                       whole_pdu, pdu_length,
1175                                       sig);
1176 }
1177
1178 static const struct gensec_security_ops gensec_schannel_security_ops = {
1179         .name           = "schannel",
1180         .auth_type      = DCERPC_AUTH_TYPE_SCHANNEL,
1181         .client_start   = schannel_client_start,
1182         .server_start   = schannel_server_start,
1183         .update_send    = schannel_update_send,
1184         .update_recv    = schannel_update_recv,
1185         .seal_packet    = schannel_seal_packet,
1186         .sign_packet    = schannel_sign_packet,
1187         .check_packet   = schannel_check_packet,
1188         .unseal_packet  = schannel_unseal_packet,
1189         .session_info   = schannel_session_info,
1190         .sig_size       = schannel_sig_size,
1191         .have_feature   = schannel_have_feature,
1192         .enabled        = true,
1193         .priority       = GENSEC_SCHANNEL
1194 };
1195
1196 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
1197 {
1198         NTSTATUS ret;
1199         ret = gensec_register(ctx, &gensec_schannel_security_ops);
1200         if (!NT_STATUS_IS_OK(ret)) {
1201                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1202                         gensec_schannel_security_ops.name));
1203                 return ret;
1204         }
1205
1206         return ret;
1207 }