~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/ntlm/ntlm.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 * (Royal Institute of Technology, Stockholm, Sweden).
4
4
 * All rights reserved.
5
5
 *
 
6
 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
 
7
 *
6
8
 * Redistribution and use in source and binary forms, with or without
7
9
 * modification, are permitted provided that the following conditions
8
10
 * are met:
41
43
#include <errno.h>
42
44
#include <limits.h>
43
45
 
 
46
#include <roken.h>
 
47
#include <parse_units.h>
44
48
#include <krb5.h>
45
 
#include <roken.h>
46
49
 
47
50
#define HC_DEPRECATED_CRYPTO
48
51
 
105
108
 */
106
109
 
107
110
#define CHECK(f, e)                                                     \
108
 
    do { ret = f ; if (ret != (e)) { ret = EINVAL; goto out; } } while(0)
 
111
    do {                                                                \
 
112
        ret = f ; if (ret != (e)) { ret = HNTLM_ERR_DECODE; goto out; } } \
 
113
    while(0)
 
114
 
 
115
static struct units ntlm_flag_units[] = {
 
116
#define ntlm_flag(x) { #x, NTLM_##x }
 
117
    ntlm_flag(ENC_56),
 
118
    ntlm_flag(NEG_KEYEX),
 
119
    ntlm_flag(ENC_128),
 
120
    ntlm_flag(MBZ1),
 
121
    ntlm_flag(MBZ2),
 
122
    ntlm_flag(MBZ3),
 
123
    ntlm_flag(NEG_VERSION),
 
124
    ntlm_flag(MBZ4),
 
125
    ntlm_flag(NEG_TARGET_INFO),
 
126
    ntlm_flag(NON_NT_SESSION_KEY),
 
127
    ntlm_flag(MBZ5),
 
128
    ntlm_flag(NEG_IDENTIFY),
 
129
    ntlm_flag(NEG_NTLM2),
 
130
    ntlm_flag(TARGET_SHARE),
 
131
    ntlm_flag(TARGET_SERVER),
 
132
    ntlm_flag(TARGET_DOMAIN),
 
133
    ntlm_flag(NEG_ALWAYS_SIGN),
 
134
    ntlm_flag(MBZ6),
 
135
    ntlm_flag(OEM_SUPPLIED_WORKSTATION),
 
136
    ntlm_flag(OEM_SUPPLIED_DOMAIN),
 
137
    ntlm_flag(NEG_ANONYMOUS),
 
138
    ntlm_flag(NEG_NT_ONLY),
 
139
    ntlm_flag(NEG_NTLM),
 
140
    ntlm_flag(MBZ8),
 
141
    ntlm_flag(NEG_LM_KEY),
 
142
    ntlm_flag(NEG_DATAGRAM),
 
143
    ntlm_flag(NEG_SEAL),
 
144
    ntlm_flag(NEG_SIGN),
 
145
    ntlm_flag(MBZ9),
 
146
    ntlm_flag(NEG_TARGET),
 
147
    ntlm_flag(NEG_OEM),
 
148
    ntlm_flag(NEG_UNICODE),
 
149
#undef ntlm_flag
 
150
    {NULL, 0}
 
151
};
 
152
 
 
153
size_t
 
154
heim_ntlm_unparse_flags(uint32_t flags, char *s, size_t len)
 
155
{
 
156
    return unparse_flags(flags, ntlm_flag_units, s, len);
 
157
}
 
158
 
109
159
 
110
160
/**
111
161
 * heim_ntlm_free_buf frees the ntlm buffer
197
247
    return len;
198
248
}
199
249
 
 
250
/*
 
251
 *
 
252
 */
 
253
 
200
254
static krb5_error_code
201
 
ret_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s)
 
255
ret_string(krb5_storage *sp, int ucs2, size_t len, char **s)
202
256
{
203
257
    krb5_error_code ret;
204
258
 
205
 
    *s = malloc(desc->length + 1);
206
 
    CHECK(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset);
207
 
    CHECK(krb5_storage_read(sp, *s, desc->length), desc->length);
208
 
    (*s)[desc->length] = '\0';
 
259
    *s = malloc(len + 1);
 
260
    if (*s == NULL)
 
261
        return ENOMEM;
 
262
    CHECK(krb5_storage_read(sp, *s, len), len);
 
263
 
 
264
    (*s)[len] = '\0';
209
265
 
210
266
    if (ucs2) {
211
267
        size_t i;
212
 
        for (i = 0; i < desc->length / 2; i++) {
 
268
        for (i = 0; i < len / 2; i++) {
213
269
            (*s)[i] = (*s)[i * 2];
214
270
            if ((*s)[i * 2 + 1]) {
215
271
                free(*s);
220
276
        (*s)[i] = '\0';
221
277
    }
222
278
    ret = 0;
223
 
out:
 
279
 out:
224
280
    return ret;
225
 
 
226
 
    return 0;
 
281
}
 
282
 
 
283
 
 
284
 
 
285
static krb5_error_code
 
286
ret_sec_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s)
 
287
{
 
288
    krb5_error_code ret = 0;
 
289
    CHECK(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset);
 
290
    CHECK(ret_string(sp, ucs2, desc->length, s), 0);
 
291
 out:
 
292
    return ret; 
227
293
}
228
294
 
229
295
static krb5_error_code
292
358
    free(ti->domainname);
293
359
    free(ti->dnsdomainname);
294
360
    free(ti->dnsservername);
 
361
    free(ti->dnstreename);
295
362
    memset(ti, 0, sizeof(*ti));
296
363
}
297
364
 
298
365
static int
299
 
encode_ti_blob(krb5_storage *out, uint16_t type, int ucs2, char *s)
 
366
encode_ti_string(krb5_storage *out, uint16_t type, int ucs2, char *s)
300
367
{
301
368
    krb5_error_code ret;
302
369
    CHECK(krb5_store_uint16(out, type), 0);
310
377
 * Encodes a ntlm_targetinfo message.
311
378
 *
312
379
 * @param ti the ntlm_targetinfo message to encode.
313
 
 * @param ucs2 if the strings should be encoded with ucs2 (selected by flag in message).
 
380
 * @param ucs2 ignored
314
381
 * @param data is the return buffer with the encoded message, should be
315
382
 * freed with heim_ntlm_free_buf().
316
383
 *
335
402
    if (out == NULL)
336
403
        return ENOMEM;
337
404
 
 
405
    krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE);
 
406
 
338
407
    if (ti->servername)
339
 
        CHECK(encode_ti_blob(out, 1, ucs2, ti->servername), 0);
 
408
        CHECK(encode_ti_string(out, 1, ucs2, ti->servername), 0);
340
409
    if (ti->domainname)
341
 
        CHECK(encode_ti_blob(out, 2, ucs2, ti->domainname), 0);
 
410
        CHECK(encode_ti_string(out, 2, ucs2, ti->domainname), 0);
342
411
    if (ti->dnsservername)
343
 
        CHECK(encode_ti_blob(out, 3, ucs2, ti->dnsservername), 0);
 
412
        CHECK(encode_ti_string(out, 3, ucs2, ti->dnsservername), 0);
344
413
    if (ti->dnsdomainname)
345
 
        CHECK(encode_ti_blob(out, 4, ucs2, ti->dnsdomainname), 0);
 
414
        CHECK(encode_ti_string(out, 4, ucs2, ti->dnsdomainname), 0);
 
415
    if (ti->dnstreename)
 
416
        CHECK(encode_ti_string(out, 5, ucs2, ti->dnstreename), 0);
 
417
    if (ti->avflags) {
 
418
        CHECK(krb5_store_uint16(out, 6), 0);
 
419
        CHECK(krb5_store_uint16(out, 4), 0);
 
420
        CHECK(krb5_store_uint32(out, ti->avflags), 0);
 
421
    }
346
422
 
347
423
    /* end tag */
348
424
    CHECK(krb5_store_int16(out, 0), 0);
377
453
                            int ucs2,
378
454
                            struct ntlm_targetinfo *ti)
379
455
{
 
456
    uint16_t type, len;
 
457
    krb5_storage *in;
 
458
    int ret = 0, done = 0;
 
459
 
380
460
    memset(ti, 0, sizeof(*ti));
381
 
    return 0;
 
461
 
 
462
    if (data->length == 0)
 
463
        return 0;
 
464
 
 
465
    in = krb5_storage_from_readonly_mem(data->data, data->length);
 
466
    if (in == NULL)
 
467
        return ENOMEM;
 
468
    krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
 
469
 
 
470
    while (!done) {
 
471
        CHECK(krb5_ret_uint16(in, &type), 0);
 
472
        CHECK(krb5_ret_uint16(in, &len), 0);
 
473
 
 
474
        switch (type) {
 
475
        case 0:
 
476
            done = 1;
 
477
            break;
 
478
        case 1:
 
479
            CHECK(ret_string(in, ucs2, len, &ti->servername), 0);
 
480
            break;
 
481
        case 2:
 
482
            CHECK(ret_string(in, ucs2, len, &ti->domainname), 0);
 
483
            break;
 
484
        case 3:
 
485
            CHECK(ret_string(in, ucs2, len, &ti->dnsservername), 0);
 
486
            break;
 
487
        case 4:
 
488
            CHECK(ret_string(in, ucs2, len, &ti->dnsdomainname), 0);
 
489
            break;
 
490
        case 5:
 
491
            CHECK(ret_string(in, ucs2, len, &ti->dnstreename), 0);
 
492
            break;
 
493
        case 6:
 
494
            CHECK(krb5_ret_uint32(in, &ti->avflags), 0);
 
495
            break;
 
496
        default:
 
497
            krb5_storage_seek(in, len, SEEK_CUR);
 
498
            break;
 
499
        }
 
500
    }
 
501
 out:
 
502
    if (in)
 
503
        krb5_storage_free(in);
 
504
    return ret;
382
505
}
383
506
 
384
507
/**
412
535
 
413
536
    in = krb5_storage_from_readonly_mem(buf->data, buf->length);
414
537
    if (in == NULL) {
415
 
        ret = EINVAL;
 
538
        ret = ENOMEM;
416
539
        goto out;
417
540
    }
418
541
    krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
422
545
    CHECK(krb5_ret_uint32(in, &type), 0);
423
546
    CHECK(type, 1);
424
547
    CHECK(krb5_ret_uint32(in, &data->flags), 0);
425
 
    if (data->flags & NTLM_SUPPLIED_DOMAIN)
 
548
    if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN)
426
549
        CHECK(ret_sec_buffer(in, &domain), 0);
427
 
    if (data->flags & NTLM_SUPPLIED_WORKSTAION)
 
550
    if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION)
428
551
        CHECK(ret_sec_buffer(in, &hostname), 0);
429
552
#if 0
430
553
    if (domain.offset > 32) {
432
555
        CHECK(krb5_ret_uint32(in, &data->os[1]), 0);
433
556
    }
434
557
#endif
435
 
    if (data->flags & NTLM_SUPPLIED_DOMAIN)
436
 
        CHECK(ret_string(in, 0, &domain, &data->domain), 0);
437
 
    if (data->flags & NTLM_SUPPLIED_WORKSTAION)
438
 
        CHECK(ret_string(in, 0, &hostname, &data->hostname), 0);
 
558
    if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN)
 
559
        CHECK(ret_sec_string(in, 0, &domain, &data->domain), 0);
 
560
    if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION)
 
561
        CHECK(ret_sec_string(in, 0, &hostname, &data->hostname), 0);
439
562
 
440
563
out:
441
564
    if (in)
472
595
 
473
596
    if (type1->domain) {
474
597
        base += 8;
475
 
        flags |= NTLM_SUPPLIED_DOMAIN;
 
598
        flags |= NTLM_OEM_SUPPLIED_DOMAIN;
476
599
    }
477
600
    if (type1->hostname) {
478
601
        base += 8;
479
 
        flags |= NTLM_SUPPLIED_WORKSTAION;
 
602
        flags |= NTLM_OEM_SUPPLIED_WORKSTATION;
480
603
    }
481
604
    if (type1->os[0])
482
605
        base += 8;
483
606
 
 
607
    domain.offset = base;
484
608
    if (type1->domain) {
485
 
        domain.offset = base;
486
609
        domain.length = len_string(0, type1->domain);
487
610
        domain.allocated = domain.length;
 
611
    } else {
 
612
        domain.length = 0;
 
613
        domain.allocated = 0;
488
614
    }
 
615
 
 
616
    hostname.offset = domain.allocated + domain.offset;
489
617
    if (type1->hostname) {
490
 
        hostname.offset = domain.allocated + domain.offset;
491
618
        hostname.length = len_string(0, type1->hostname);
492
619
        hostname.allocated = hostname.length;
 
620
    } else {
 
621
        hostname.length = 0;
 
622
        hostname.allocated = 0;
493
623
    }
494
624
 
495
625
    out = krb5_storage_emem();
502
632
    CHECK(krb5_store_uint32(out, 1), 0);
503
633
    CHECK(krb5_store_uint32(out, flags), 0);
504
634
 
505
 
    if (type1->domain)
506
 
        CHECK(store_sec_buffer(out, &domain), 0);
507
 
    if (type1->hostname)
508
 
        CHECK(store_sec_buffer(out, &hostname), 0);
509
 
    if (type1->os[0]) {
 
635
    CHECK(store_sec_buffer(out, &domain), 0);
 
636
    CHECK(store_sec_buffer(out, &hostname), 0);
 
637
#if 0
510
638
        CHECK(krb5_store_uint32(out, type1->os[0]), 0);
511
639
        CHECK(krb5_store_uint32(out, type1->os[1]), 0);
512
 
    }
 
640
#endif
513
641
    if (type1->domain)
514
642
        CHECK(put_string(out, 0, type1->domain), 0);
515
643
    if (type1->hostname)
558
686
 
559
687
    in = krb5_storage_from_readonly_mem(buf->data, buf->length);
560
688
    if (in == NULL) {
561
 
        ret = EINVAL;
 
689
        ret = ENOMEM;
562
690
        goto out;
563
691
    }
564
692
    krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
572
700
    CHECK(krb5_ret_uint32(in, &type2->flags), 0);
573
701
    if (type2->flags & NTLM_NEG_UNICODE)
574
702
        ucs2 = 1;
575
 
    CHECK(krb5_storage_read(in, type2->challange, sizeof(type2->challange)),
576
 
          sizeof(type2->challange));
 
703
    CHECK(krb5_storage_read(in, type2->challenge, sizeof(type2->challenge)),
 
704
          sizeof(type2->challenge));
577
705
    CHECK(krb5_ret_uint32(in, &ctx[0]), 0); /* context */
578
706
    CHECK(krb5_ret_uint32(in, &ctx[1]), 0);
579
707
    CHECK(ret_sec_buffer(in, &targetinfo), 0);
580
708
    /* os version */
581
 
#if 0
582
 
    CHECK(krb5_ret_uint32(in, &type2->os[0]), 0);
583
 
    CHECK(krb5_ret_uint32(in, &type2->os[1]), 0);
584
 
#endif
 
709
    if (type2->flags & NTLM_NEG_VERSION) {
 
710
        CHECK(krb5_ret_uint32(in, &type2->os[0]), 0);
 
711
        CHECK(krb5_ret_uint32(in, &type2->os[1]), 0);
 
712
    }
585
713
 
586
 
    CHECK(ret_string(in, ucs2, &targetname, &type2->targetname), 0);
 
714
    CHECK(ret_sec_string(in, ucs2, &targetname, &type2->targetname), 0);
587
715
    CHECK(ret_buf(in, &targetinfo, &type2->targetinfo), 0);
588
716
    ret = 0;
589
717
 
618
746
    uint32_t base;
619
747
    int ucs2 = 0;
620
748
 
621
 
    if (type2->os[0])
622
 
        base = 56;
623
 
    else
624
 
        base = 48;
 
749
    base = 48;
 
750
 
 
751
    if (type2->flags & NTLM_NEG_VERSION)
 
752
        base += 8;
625
753
 
626
754
    if (type2->flags & NTLM_NEG_UNICODE)
627
755
        ucs2 = 1;
644
772
    CHECK(krb5_store_uint32(out, 2), 0);
645
773
    CHECK(store_sec_buffer(out, &targetname), 0);
646
774
    CHECK(krb5_store_uint32(out, type2->flags), 0);
647
 
    CHECK(krb5_storage_write(out, type2->challange, sizeof(type2->challange)),
648
 
          sizeof(type2->challange));
 
775
    CHECK(krb5_storage_write(out, type2->challenge, sizeof(type2->challenge)),
 
776
          sizeof(type2->challenge));
649
777
    CHECK(krb5_store_uint32(out, 0), 0); /* context */
650
778
    CHECK(krb5_store_uint32(out, 0), 0);
651
779
    CHECK(store_sec_buffer(out, &targetinfo), 0);
652
780
    /* os version */
653
 
    if (type2->os[0]) {
 
781
    if (type2->flags & NTLM_NEG_VERSION) {
654
782
        CHECK(krb5_store_uint32(out, type2->os[0]), 0);
655
783
        CHECK(krb5_store_uint32(out, type2->os[1]), 0);
656
784
    }
709
837
    uint32_t type;
710
838
    krb5_storage *in;
711
839
    struct sec_buffer lm, ntlm, target, username, sessionkey, ws;
 
840
    uint32_t min_offset = 72;
712
841
 
713
842
    memset(type3, 0, sizeof(*type3));
714
843
    memset(&sessionkey, 0, sizeof(sessionkey));
715
844
 
716
845
    in = krb5_storage_from_readonly_mem(buf->data, buf->length);
717
846
    if (in == NULL) {
718
 
        ret = EINVAL;
 
847
        ret = ENOMEM;
719
848
        goto out;
720
849
    }
721
850
    krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE);
725
854
    CHECK(krb5_ret_uint32(in, &type), 0);
726
855
    CHECK(type, 3);
727
856
    CHECK(ret_sec_buffer(in, &lm), 0);
 
857
    if (lm.allocated)
 
858
        min_offset = min(min_offset, lm.offset);
728
859
    CHECK(ret_sec_buffer(in, &ntlm), 0);
 
860
    if (ntlm.allocated)
 
861
        min_offset = min(min_offset, ntlm.offset);
729
862
    CHECK(ret_sec_buffer(in, &target), 0);
 
863
    if (target.allocated)
 
864
        min_offset = min(min_offset, target.offset);
730
865
    CHECK(ret_sec_buffer(in, &username), 0);
 
866
    if (username.allocated)
 
867
        min_offset = min(min_offset, username.offset);
731
868
    CHECK(ret_sec_buffer(in, &ws), 0);
732
 
    if (lm.offset >= 60) {
 
869
    if (ws.allocated)
 
870
        min_offset = min(min_offset, ws.offset);
 
871
 
 
872
    if (min_offset > 52) {
733
873
        CHECK(ret_sec_buffer(in, &sessionkey), 0);
734
 
    }
735
 
    if (lm.offset >= 64) {
 
874
        min_offset = max(min_offset, sessionkey.offset);
736
875
        CHECK(krb5_ret_uint32(in, &type3->flags), 0);
737
876
    }
738
 
    if (lm.offset >= 72) {
 
877
    if (min_offset > 52 + 8 + 4 + 8) {
739
878
        CHECK(krb5_ret_uint32(in, &type3->os[0]), 0);
740
879
        CHECK(krb5_ret_uint32(in, &type3->os[1]), 0);
741
880
    }
742
881
    CHECK(ret_buf(in, &lm, &type3->lm), 0);
743
882
    CHECK(ret_buf(in, &ntlm, &type3->ntlm), 0);
744
 
    CHECK(ret_string(in, ucs2, &target, &type3->targetname), 0);
745
 
    CHECK(ret_string(in, ucs2, &username, &type3->username), 0);
746
 
    CHECK(ret_string(in, ucs2, &ws, &type3->ws), 0);
 
883
    CHECK(ret_sec_string(in, ucs2, &target, &type3->targetname), 0);
 
884
    CHECK(ret_sec_string(in, ucs2, &username, &type3->username), 0);
 
885
    CHECK(ret_sec_string(in, ucs2, &ws, &type3->ws), 0);
747
886
    if (sessionkey.offset)
748
887
        CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0);
749
888
 
786
925
    memset(&sessionkey, 0, sizeof(sessionkey));
787
926
 
788
927
    base = 52;
789
 
    if (type3->sessionkey.length) {
790
 
        base += 8; /* sessionkey sec buf */
791
 
        base += 4; /* flags */
792
 
    }
 
928
 
 
929
    base += 8; /* sessionkey sec buf */
 
930
    base += 4; /* flags */
 
931
 
793
932
    if (type3->os[0]) {
794
933
        base += 8;
795
934
    }
797
936
    if (type3->flags & NTLM_NEG_UNICODE)
798
937
        ucs2 = 1;
799
938
 
800
 
    lm.offset = base;
801
 
    lm.length = type3->lm.length;
802
 
    lm.allocated = type3->lm.length;
803
 
 
804
 
    ntlm.offset = lm.offset + lm.allocated;
805
 
    ntlm.length = type3->ntlm.length;
806
 
    ntlm.allocated = ntlm.length;
807
 
 
808
 
    target.offset = ntlm.offset + ntlm.allocated;
 
939
    target.offset = base;
809
940
    target.length = len_string(ucs2, type3->targetname);
810
941
    target.allocated = target.length;
811
942
 
817
948
    ws.length = len_string(ucs2, type3->ws);
818
949
    ws.allocated = ws.length;
819
950
 
820
 
    sessionkey.offset = ws.offset + ws.allocated;
 
951
    lm.offset = ws.offset + ws.allocated;
 
952
    lm.length = type3->lm.length;
 
953
    lm.allocated = type3->lm.length;
 
954
 
 
955
    ntlm.offset = lm.offset + lm.allocated;
 
956
    ntlm.length = type3->ntlm.length;
 
957
    ntlm.allocated = ntlm.length;
 
958
 
 
959
    sessionkey.offset = ntlm.offset + ntlm.allocated;
821
960
    sessionkey.length = type3->sessionkey.length;
822
961
    sessionkey.allocated = type3->sessionkey.length;
823
962
 
835
974
    CHECK(store_sec_buffer(out, &target), 0);
836
975
    CHECK(store_sec_buffer(out, &username), 0);
837
976
    CHECK(store_sec_buffer(out, &ws), 0);
838
 
    /* optional */
839
 
    if (type3->sessionkey.length) {
840
 
        CHECK(store_sec_buffer(out, &sessionkey), 0);
841
 
        CHECK(krb5_store_uint32(out, type3->flags), 0);
842
 
    }
 
977
    CHECK(store_sec_buffer(out, &sessionkey), 0);
 
978
    CHECK(krb5_store_uint32(out, type3->flags), 0);
 
979
 
843
980
#if 0
844
981
    CHECK(krb5_store_uint32(out, 0), 0); /* os0 */
845
982
    CHECK(krb5_store_uint32(out, 0), 0); /* os1 */
846
983
#endif
847
984
 
848
 
    CHECK(put_buf(out, &type3->lm), 0);
849
 
    CHECK(put_buf(out, &type3->ntlm), 0);
850
985
    CHECK(put_string(out, ucs2, type3->targetname), 0);
851
986
    CHECK(put_string(out, ucs2, type3->username), 0);
852
987
    CHECK(put_string(out, ucs2, type3->ws), 0);
 
988
    CHECK(put_buf(out, &type3->lm), 0);
 
989
    CHECK(put_buf(out, &type3->ntlm), 0);
853
990
    CHECK(put_buf(out, &type3->sessionkey), 0);
854
991
 
855
992
    {
872
1009
 
873
1010
static void
874
1011
splitandenc(unsigned char *hash,
875
 
            unsigned char *challange,
 
1012
            unsigned char *challenge,
876
1013
            unsigned char *answer)
877
1014
{
878
 
    DES_cblock key;
879
 
    DES_key_schedule sched;
880
 
 
881
 
    ((unsigned char*)key)[0] =  hash[0];
882
 
    ((unsigned char*)key)[1] = (hash[0] << 7) | (hash[1] >> 1);
883
 
    ((unsigned char*)key)[2] = (hash[1] << 6) | (hash[2] >> 2);
884
 
    ((unsigned char*)key)[3] = (hash[2] << 5) | (hash[3] >> 3);
885
 
    ((unsigned char*)key)[4] = (hash[3] << 4) | (hash[4] >> 4);
886
 
    ((unsigned char*)key)[5] = (hash[4] << 3) | (hash[5] >> 5);
887
 
    ((unsigned char*)key)[6] = (hash[5] << 2) | (hash[6] >> 6);
888
 
    ((unsigned char*)key)[7] = (hash[6] << 1);
889
 
 
890
 
    DES_set_odd_parity(&key);
891
 
    DES_set_key_unchecked(&key, &sched);
892
 
    DES_ecb_encrypt((DES_cblock *)challange, (DES_cblock *)answer, &sched, 1);
893
 
    memset(&sched, 0, sizeof(sched));
 
1015
    EVP_CIPHER_CTX ctx;
 
1016
    unsigned char key[8];
 
1017
 
 
1018
    key[0] =  hash[0];
 
1019
    key[1] = (hash[0] << 7) | (hash[1] >> 1);
 
1020
    key[2] = (hash[1] << 6) | (hash[2] >> 2);
 
1021
    key[3] = (hash[2] << 5) | (hash[3] >> 3);
 
1022
    key[4] = (hash[3] << 4) | (hash[4] >> 4);
 
1023
    key[5] = (hash[4] << 3) | (hash[5] >> 5);
 
1024
    key[6] = (hash[5] << 2) | (hash[6] >> 6);
 
1025
    key[7] = (hash[6] << 1);
 
1026
 
 
1027
    EVP_CIPHER_CTX_init(&ctx);
 
1028
    
 
1029
    EVP_CipherInit_ex(&ctx, EVP_des_cbc(), NULL, key, NULL, 1);
 
1030
    EVP_Cipher(&ctx, answer, challenge, 8);
 
1031
    EVP_CIPHER_CTX_cleanup(&ctx);
894
1032
    memset(key, 0, sizeof(key));
895
1033
}
896
1034
 
910
1048
heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
911
1049
{
912
1050
    struct ntlm_buf buf;
913
 
    MD4_CTX ctx;
 
1051
    EVP_MD_CTX *m;
914
1052
    int ret;
915
1053
 
916
1054
    key->data = malloc(MD5_DIGEST_LENGTH);
923
1061
        heim_ntlm_free_buf(key);
924
1062
        return ret;
925
1063
    }
926
 
    MD4_Init(&ctx);
927
 
    MD4_Update(&ctx, buf.data, buf.length);
928
 
    MD4_Final(key->data, &ctx);
 
1064
 
 
1065
    m = EVP_MD_CTX_create();
 
1066
    if (m == NULL) {
 
1067
        heim_ntlm_free_buf(key);
 
1068
        heim_ntlm_free_buf(&buf);
 
1069
        return ENOMEM;
 
1070
    }
 
1071
 
 
1072
    EVP_DigestInit_ex(m, EVP_md4(), NULL);
 
1073
    EVP_DigestUpdate(m, buf.data, buf.length);
 
1074
    EVP_DigestFinal_ex(m, key->data, NULL);
 
1075
    EVP_MD_CTX_destroy(m);
 
1076
 
929
1077
    heim_ntlm_free_buf(&buf);
930
1078
    return 0;
931
1079
}
935
1083
 *
936
1084
 * @param key the ntlm v1 key
937
1085
 * @param len length of key
938
 
 * @param challange sent by the server
 
1086
 * @param challenge sent by the server
939
1087
 * @param answer calculated answer, should be freed with heim_ntlm_free_buf().
940
1088
 *
941
1089
 * @return In case of success 0 is return, an errors, a errno in what
946
1094
 
947
1095
int
948
1096
heim_ntlm_calculate_ntlm1(void *key, size_t len,
949
 
                          unsigned char challange[8],
 
1097
                          unsigned char challenge[8],
950
1098
                          struct ntlm_buf *answer)
951
1099
{
952
1100
    unsigned char res[21];
953
1101
 
954
1102
    if (len != MD4_DIGEST_LENGTH)
955
 
        return EINVAL;
 
1103
        return HNTLM_ERR_INVALID_LENGTH;
956
1104
 
957
1105
    memcpy(res, key, len);
958
1106
    memset(&res[MD4_DIGEST_LENGTH], 0, sizeof(res) - MD4_DIGEST_LENGTH);
962
1110
        return ENOMEM;
963
1111
    answer->length = 24;
964
1112
 
965
 
    splitandenc(&res[0],  challange, ((unsigned char *)answer->data) + 0);
966
 
    splitandenc(&res[7],  challange, ((unsigned char *)answer->data) + 8);
967
 
    splitandenc(&res[14], challange, ((unsigned char *)answer->data) + 16);
968
 
 
969
 
    return 0;
970
 
}
 
1113
    splitandenc(&res[0],  challenge, ((unsigned char *)answer->data) + 0);
 
1114
    splitandenc(&res[7],  challenge, ((unsigned char *)answer->data) + 8);
 
1115
    splitandenc(&res[14], challenge, ((unsigned char *)answer->data) + 16);
 
1116
 
 
1117
    return 0;
 
1118
}
 
1119
 
 
1120
int
 
1121
heim_ntlm_v1_base_session(void *key, size_t len,
 
1122
                          struct ntlm_buf *session)
 
1123
{
 
1124
    EVP_MD_CTX *m;
 
1125
 
 
1126
    session->length = MD4_DIGEST_LENGTH;
 
1127
    session->data = malloc(session->length);
 
1128
    if (session->data == NULL) {
 
1129
        session->length = 0;
 
1130
        return ENOMEM;
 
1131
    }
 
1132
    
 
1133
    m = EVP_MD_CTX_create();
 
1134
    if (m == NULL) {
 
1135
        heim_ntlm_free_buf(session);
 
1136
        return ENOMEM;
 
1137
    }
 
1138
    EVP_DigestInit_ex(m, EVP_md4(), NULL);
 
1139
    EVP_DigestUpdate(m, key, len);
 
1140
    EVP_DigestFinal_ex(m, session->data, NULL);
 
1141
    EVP_MD_CTX_destroy(m);
 
1142
 
 
1143
    return 0;
 
1144
}
 
1145
 
 
1146
int
 
1147
heim_ntlm_v2_base_session(void *key, size_t len,
 
1148
                          struct ntlm_buf *ntlmResponse,
 
1149
                          struct ntlm_buf *session)
 
1150
{
 
1151
    unsigned int hmaclen;
 
1152
    HMAC_CTX c;
 
1153
 
 
1154
    if (ntlmResponse->length <= 16)
 
1155
        return HNTLM_ERR_INVALID_LENGTH;
 
1156
 
 
1157
    session->data = malloc(16);
 
1158
    if (session->data == NULL)
 
1159
        return ENOMEM;
 
1160
    session->length = 16;
 
1161
 
 
1162
    /* Note: key is the NTLMv2 key */
 
1163
    HMAC_CTX_init(&c);
 
1164
    HMAC_Init_ex(&c, key, len, EVP_md5(), NULL);
 
1165
    HMAC_Update(&c, ntlmResponse->data, 16);
 
1166
    HMAC_Final(&c, session->data, &hmaclen);
 
1167
    HMAC_CTX_cleanup(&c);
 
1168
 
 
1169
    return 0;
 
1170
}
 
1171
 
 
1172
 
 
1173
int
 
1174
heim_ntlm_keyex_wrap(struct ntlm_buf *base_session,
 
1175
                     struct ntlm_buf *session,
 
1176
                     struct ntlm_buf *encryptedSession)
 
1177
{
 
1178
    EVP_CIPHER_CTX c;
 
1179
    int ret;
 
1180
 
 
1181
    session->length = MD4_DIGEST_LENGTH;
 
1182
    session->data = malloc(session->length);
 
1183
    if (session->data == NULL) {
 
1184
        session->length = 0;
 
1185
        return ENOMEM;
 
1186
    }
 
1187
    encryptedSession->length = MD4_DIGEST_LENGTH;
 
1188
    encryptedSession->data = malloc(encryptedSession->length);
 
1189
    if (encryptedSession->data == NULL) {
 
1190
        heim_ntlm_free_buf(session);
 
1191
        encryptedSession->length = 0;
 
1192
        return ENOMEM;
 
1193
    }
 
1194
 
 
1195
    EVP_CIPHER_CTX_init(&c);
 
1196
 
 
1197
    ret = EVP_CipherInit_ex(&c, EVP_rc4(), NULL, base_session->data, NULL, 1);
 
1198
    if (ret != 1) {
 
1199
        EVP_CIPHER_CTX_cleanup(&c);
 
1200
        heim_ntlm_free_buf(encryptedSession);
 
1201
        heim_ntlm_free_buf(session);
 
1202
        return HNTLM_ERR_CRYPTO;
 
1203
    }
 
1204
 
 
1205
    if (RAND_bytes(session->data, session->length) != 1) {
 
1206
        EVP_CIPHER_CTX_cleanup(&c);
 
1207
        heim_ntlm_free_buf(encryptedSession);
 
1208
        heim_ntlm_free_buf(session);
 
1209
        return HNTLM_ERR_RAND;
 
1210
    }
 
1211
 
 
1212
    EVP_Cipher(&c, encryptedSession->data, session->data, encryptedSession->length);
 
1213
    EVP_CIPHER_CTX_cleanup(&c);
 
1214
 
 
1215
    return 0;
 
1216
 
 
1217
 
 
1218
 
 
1219
}
 
1220
 
 
1221
 
971
1222
 
972
1223
/**
973
1224
 * Generates an NTLMv1 session random with assosited session master key.
988
1239
                             struct ntlm_buf *session,
989
1240
                             struct ntlm_buf *master)
990
1241
{
991
 
    RC4_KEY rc4;
992
 
 
993
 
    memset(master, 0, sizeof(*master));
 
1242
    struct ntlm_buf sess;
 
1243
    int ret;
 
1244
 
 
1245
    ret = heim_ntlm_v1_base_session(key, len, &sess);
 
1246
    if (ret)
 
1247
        return ret;
 
1248
 
 
1249
    ret = heim_ntlm_keyex_wrap(&sess, session, master);
 
1250
    heim_ntlm_free_buf(&sess);
 
1251
 
 
1252
    return ret;
 
1253
}
 
1254
 
 
1255
/**
 
1256
 * Generates an NTLMv2 session random with associated session master key.
 
1257
 *
 
1258
 * @param key the NTLMv2 key
 
1259
 * @param len length of key
 
1260
 * @param blob the NTLMv2 "blob"
 
1261
 * @param session generated session nonce, should be freed with heim_ntlm_free_buf().
 
1262
 * @param master calculated session master key, should be freed with heim_ntlm_free_buf().
 
1263
 *
 
1264
 * @return In case of success 0 is return, an errors, a errno in what
 
1265
 * went wrong.
 
1266
 *
 
1267
 * @ingroup ntlm_core
 
1268
 */
 
1269
 
 
1270
 
 
1271
int
 
1272
heim_ntlm_build_ntlm2_master(void *key, size_t len,
 
1273
                             struct ntlm_buf *blob,
 
1274
                             struct ntlm_buf *session,
 
1275
                             struct ntlm_buf *master)
 
1276
{
 
1277
    struct ntlm_buf sess;
 
1278
    int ret;
 
1279
 
 
1280
    ret = heim_ntlm_v2_base_session(key, len, blob, &sess);
 
1281
    if (ret)
 
1282
        return ret;
 
1283
 
 
1284
    ret = heim_ntlm_keyex_wrap(&sess, session, master);
 
1285
    heim_ntlm_free_buf(&sess);
 
1286
 
 
1287
    return ret;
 
1288
}
 
1289
 
 
1290
/**
 
1291
 * Given a key and encrypted session, unwrap the session key
 
1292
 *
 
1293
 * @param baseKey the sessionBaseKey
 
1294
 * @param encryptedSession encrypted session, type3.session field.
 
1295
 * @param session generated session nonce, should be freed with heim_ntlm_free_buf().
 
1296
 *
 
1297
 * @return In case of success 0 is return, an errors, a errno in what
 
1298
 * went wrong.
 
1299
 *
 
1300
 * @ingroup ntlm_core
 
1301
 */
 
1302
 
 
1303
int
 
1304
heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey,
 
1305
                       struct ntlm_buf *encryptedSession,
 
1306
                       struct ntlm_buf *session)
 
1307
{
 
1308
    EVP_CIPHER_CTX c;
 
1309
 
994
1310
    memset(session, 0, sizeof(*session));
995
1311
 
996
 
    if (len != MD4_DIGEST_LENGTH)
997
 
        return EINVAL;
 
1312
    if (baseKey->length != MD4_DIGEST_LENGTH)
 
1313
        return HNTLM_ERR_INVALID_LENGTH;
998
1314
 
999
1315
    session->length = MD4_DIGEST_LENGTH;
1000
1316
    session->data = malloc(session->length);
1001
1317
    if (session->data == NULL) {
1002
1318
        session->length = 0;
1003
 
        return EINVAL;
1004
 
    }
1005
 
    master->length = MD4_DIGEST_LENGTH;
1006
 
    master->data = malloc(master->length);
1007
 
    if (master->data == NULL) {
1008
 
        heim_ntlm_free_buf(master);
1009
 
        heim_ntlm_free_buf(session);
1010
 
        return EINVAL;
1011
 
    }
1012
 
 
1013
 
    {
1014
 
        unsigned char sessionkey[MD4_DIGEST_LENGTH];
1015
 
        MD4_CTX ctx;
1016
 
 
1017
 
        MD4_Init(&ctx);
1018
 
        MD4_Update(&ctx, key, len);
1019
 
        MD4_Final(sessionkey, &ctx);
1020
 
        
1021
 
        RC4_set_key(&rc4, sizeof(sessionkey), sessionkey);
1022
 
    }
1023
 
 
1024
 
    if (RAND_bytes(session->data, session->length) != 1) {
1025
 
        heim_ntlm_free_buf(master);
1026
 
        heim_ntlm_free_buf(session);
1027
 
        return EINVAL;
1028
 
    }
1029
 
 
1030
 
    RC4(&rc4, master->length, session->data, master->data);
1031
 
    memset(&rc4, 0, sizeof(rc4));
 
1319
        return ENOMEM;
 
1320
    }
 
1321
    EVP_CIPHER_CTX_init(&c);
 
1322
 
 
1323
    if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) {
 
1324
        EVP_CIPHER_CTX_cleanup(&c);
 
1325
        heim_ntlm_free_buf(session);
 
1326
        return HNTLM_ERR_CRYPTO;
 
1327
    }
 
1328
 
 
1329
    EVP_Cipher(&c, session->data, encryptedSession->data, session->length);
 
1330
    EVP_CIPHER_CTX_cleanup(&c);
1032
1331
 
1033
1332
    return 0;
1034
1333
}
1035
1334
 
 
1335
 
1036
1336
/**
1037
1337
 * Generates an NTLMv2 session key.
1038
1338
 *
1104
1404
    return (time_t)t;
1105
1405
}
1106
1406
 
 
1407
/**
 
1408
 * Calculate LMv2 response
 
1409
 *
 
1410
 * @param key the ntlm key
 
1411
 * @param len length of key
 
1412
 * @param username name of the user, as sent in the message, assumed to be in UTF8.
 
1413
 * @param target the name of the target, assumed to be in UTF8.
 
1414
 * @param serverchallenge challenge as sent by the server in the type2 message.
 
1415
 * @param ntlmv2 calculated session key
 
1416
 * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
 
1417
 *
 
1418
 * @return In case of success 0 is return, an errors, a errno in what
 
1419
 * went wrong.
 
1420
 *
 
1421
 * @ingroup ntlm_core
 
1422
 */
 
1423
 
 
1424
int
 
1425
heim_ntlm_calculate_lm2(const void *key, size_t len,
 
1426
                        const char *username,
 
1427
                        const char *target,
 
1428
                        const unsigned char serverchallenge[8],
 
1429
                        unsigned char ntlmv2[16],
 
1430
                        struct ntlm_buf *answer)
 
1431
{
 
1432
    unsigned char clientchallenge[8];
 
1433
 
 
1434
    if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1)
 
1435
        return HNTLM_ERR_RAND;
 
1436
 
 
1437
    /* calculate ntlmv2 key */
 
1438
 
 
1439
    heim_ntlm_ntlmv2_key(key, len, username, target, ntlmv2);
 
1440
 
 
1441
    answer->data = malloc(24);
 
1442
    if (answer->data == NULL)
 
1443
        return ENOMEM;
 
1444
    answer->length = 24;
 
1445
 
 
1446
    heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8,
 
1447
                                serverchallenge, answer->data);
 
1448
 
 
1449
    memcpy(((uint8_t *)answer->data) + 16, clientchallenge, 8);
 
1450
 
 
1451
    return 0;
 
1452
}
 
1453
 
1107
1454
 
1108
1455
/**
1109
1456
 * Calculate NTLMv2 response
1112
1459
 * @param len length of key
1113
1460
 * @param username name of the user, as sent in the message, assumed to be in UTF8.
1114
1461
 * @param target the name of the target, assumed to be in UTF8.
1115
 
 * @param serverchallange challange as sent by the server in the type2 message.
 
1462
 * @param serverchallenge challenge as sent by the server in the type2 message.
1116
1463
 * @param infotarget infotarget as sent by the server in the type2 message.
1117
1464
 * @param ntlmv2 calculated session key
1118
1465
 * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
1127
1474
heim_ntlm_calculate_ntlm2(const void *key, size_t len,
1128
1475
                          const char *username,
1129
1476
                          const char *target,
1130
 
                          const unsigned char serverchallange[8],
 
1477
                          const unsigned char serverchallenge[8],
1131
1478
                          const struct ntlm_buf *infotarget,
1132
1479
                          unsigned char ntlmv2[16],
1133
1480
                          struct ntlm_buf *answer)
1134
1481
{
1135
1482
    krb5_error_code ret;
1136
1483
    krb5_data data;
1137
 
    unsigned int hmaclen;
1138
1484
    unsigned char ntlmv2answer[16];
1139
1485
    krb5_storage *sp;
1140
 
    unsigned char clientchallange[8];
1141
 
    HMAC_CTX c;
 
1486
    unsigned char clientchallenge[8];
1142
1487
    uint64_t t;
1143
1488
 
1144
1489
    t = unix2nttime(time(NULL));
1145
1490
 
1146
 
    if (RAND_bytes(clientchallange, sizeof(clientchallange)) != 1)
1147
 
        return EINVAL;
 
1491
    if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1)
 
1492
        return HNTLM_ERR_RAND;
1148
1493
 
1149
1494
    /* calculate ntlmv2 key */
1150
1495
 
1163
1508
    CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0);
1164
1509
    CHECK(krb5_store_uint32(sp, t >> 32), 0);
1165
1510
 
1166
 
    CHECK(krb5_storage_write(sp, clientchallange, 8), 8);
 
1511
    CHECK(krb5_storage_write(sp, clientchallenge, 8), 8);
1167
1512
 
1168
1513
    CHECK(krb5_store_uint32(sp, 0), 0);  /* unknown but zero will work */
1169
1514
    CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length),
1174
1519
    krb5_storage_free(sp);
1175
1520
    sp = NULL;
1176
1521
 
1177
 
    HMAC_CTX_init(&c);
1178
 
    HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
1179
 
    HMAC_Update(&c, serverchallange, 8);
1180
 
    HMAC_Update(&c, data.data, data.length);
1181
 
    HMAC_Final(&c, ntlmv2answer, &hmaclen);
1182
 
    HMAC_CTX_cleanup(&c);
 
1522
    heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer);
1183
1523
 
1184
1524
    sp = krb5_storage_emem();
1185
1525
    if (sp == NULL) {
1215
1555
 * @param username name of the user, as sent in the message, assumed to be in UTF8.
1216
1556
 * @param target the name of the target, assumed to be in UTF8.
1217
1557
 * @param now the time now (0 if the library should pick it up itself)
1218
 
 * @param serverchallange challange as sent by the server in the type2 message.
 
1558
 * @param serverchallenge challenge as sent by the server in the type2 message.
1219
1559
 * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
1220
1560
 * @param infotarget infotarget as sent by the server in the type2 message.
1221
1561
 * @param ntlmv2 calculated session key
1231
1571
                       const char *username,
1232
1572
                       const char *target,
1233
1573
                       time_t now,
1234
 
                       const unsigned char serverchallange[8],
 
1574
                       const unsigned char serverchallenge[8],
1235
1575
                       const struct ntlm_buf *answer,
1236
1576
                       struct ntlm_buf *infotarget,
1237
1577
                       unsigned char ntlmv2[16])
1238
1578
{
1239
1579
    krb5_error_code ret;
1240
 
    unsigned int hmaclen;
1241
1580
    unsigned char clientanswer[16];
1242
1581
    unsigned char clientnonce[8];
1243
1582
    unsigned char serveranswer[16];
1244
1583
    krb5_storage *sp;
1245
 
    HMAC_CTX c;
1246
 
    uint64_t t;
1247
1584
    time_t authtime;
1248
1585
    uint32_t temp;
 
1586
    uint64_t t;
1249
1587
 
1250
1588
    infotarget->length = 0;
1251
1589
    infotarget->data = NULL;
1252
1590
 
1253
1591
    if (answer->length < 16)
1254
 
        return EINVAL;
 
1592
        return HNTLM_ERR_INVALID_LENGTH;
1255
1593
 
1256
1594
    if (now == 0)
1257
1595
        now = time(NULL);
1282
1620
    authtime = nt2unixtime(t);
1283
1621
 
1284
1622
    if (abs((int)(authtime - now)) > authtimediff) {
1285
 
        ret = EINVAL;
 
1623
        ret = HNTLM_ERR_TIME_SKEW;
1286
1624
        goto out;
1287
1625
    }
1288
1626
 
1289
 
    /* client challange */
 
1627
    /* client challenge */
1290
1628
    CHECK(krb5_storage_read(sp, clientnonce, 8), 8);
1291
1629
 
1292
1630
    CHECK(krb5_ret_uint32(sp, &temp), 0); /* unknown */
1304
1642
    krb5_storage_free(sp);
1305
1643
    sp = NULL;
1306
1644
 
1307
 
    HMAC_CTX_init(&c);
1308
 
    HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
1309
 
    HMAC_Update(&c, serverchallange, 8);
1310
 
    HMAC_Update(&c, ((unsigned char *)answer->data) + 16, answer->length - 16);
1311
 
    HMAC_Final(&c, serveranswer, &hmaclen);
1312
 
    HMAC_CTX_cleanup(&c);
 
1645
    if (answer->length < 16) {
 
1646
        ret = HNTLM_ERR_INVALID_LENGTH;
 
1647
        goto out;
 
1648
    }
 
1649
 
 
1650
    heim_ntlm_derive_ntlm2_sess(ntlmv2,
 
1651
                                ((unsigned char *)answer->data) + 16, answer->length - 16,
 
1652
                                serverchallenge,
 
1653
                                serveranswer);
1313
1654
 
1314
1655
    if (memcmp(serveranswer, clientanswer, 16) != 0) {
1315
1656
        heim_ntlm_free_buf(infotarget);
1316
 
        return EINVAL;
 
1657
        return HNTLM_ERR_AUTH;
1317
1658
    }
1318
1659
 
1319
1660
    return 0;
1347
1688
                               struct ntlm_buf *lm,
1348
1689
                               struct ntlm_buf *ntlm)
1349
1690
{
1350
 
    unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
 
1691
    unsigned char ntlm2_sess_hash[8];
1351
1692
    unsigned char res[21], *resp;
1352
 
    MD5_CTX md5;
 
1693
    int code;
 
1694
 
 
1695
    code = heim_ntlm_calculate_ntlm2_sess_hash(clnt_nonce, svr_chal,
 
1696
                                               ntlm2_sess_hash);
 
1697
    if (code) {
 
1698
        return code;
 
1699
    }
1353
1700
 
1354
1701
    lm->data = malloc(24);
1355
 
    if (lm->data == NULL)
 
1702
    if (lm->data == NULL) {
1356
1703
        return ENOMEM;
 
1704
    }
1357
1705
    lm->length = 24;
1358
1706
 
1359
1707
    ntlm->data = malloc(24);
1368
1716
    memset(lm->data, 0, 24);
1369
1717
    memcpy(lm->data, clnt_nonce, 8);
1370
1718
 
1371
 
    MD5_Init(&md5);
1372
 
    MD5_Update(&md5, svr_chal, 8); /* session nonce part 1 */
1373
 
    MD5_Update(&md5, clnt_nonce, 8); /* session nonce part 2 */
1374
 
    MD5_Final(ntlm2_sess_hash, &md5); /* will only use first 8 bytes */
1375
 
 
1376
1719
    memset(res, 0, sizeof(res));
1377
1720
    memcpy(res, ntlm_hash, 16);
1378
1721
 
1383
1726
 
1384
1727
    return 0;
1385
1728
}
 
1729
 
 
1730
 
 
1731
/*
 
1732
 * Calculate the NTLM2 Session "Verifier"
 
1733
 *
 
1734
 * @param clnt_nonce client nonce
 
1735
 * @param svr_chal server challage
 
1736
 * @param hash The NTLM session verifier
 
1737
 *
 
1738
 * @return In case of success 0 is return, an errors, a errno in what
 
1739
 * went wrong.
 
1740
 *
 
1741
 * @ingroup ntlm_core
 
1742
 */
 
1743
 
 
1744
int
 
1745
heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8],
 
1746
                                    const unsigned char svr_chal[8],
 
1747
                                    unsigned char verifier[8])
 
1748
{
 
1749
    unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
 
1750
    EVP_MD_CTX *m;
 
1751
 
 
1752
    m = EVP_MD_CTX_create();
 
1753
    if (m == NULL)
 
1754
        return ENOMEM;
 
1755
 
 
1756
    EVP_DigestInit_ex(m, EVP_md5(), NULL);
 
1757
    EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */
 
1758
    EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */
 
1759
    EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */
 
1760
    EVP_MD_CTX_destroy(m);
 
1761
 
 
1762
    memcpy(verifier, ntlm2_sess_hash, 8);
 
1763
 
 
1764
    return 0;
 
1765
}
 
1766
 
 
1767
 
 
1768
/*
 
1769
 * Derive a NTLM2 session key
 
1770
 *
 
1771
 * @param sessionkey session key from domain controller
 
1772
 * @param clnt_nonce client nonce
 
1773
 * @param svr_chal server challenge
 
1774
 * @param derivedkey salted session key
 
1775
 *
 
1776
 * @return In case of success 0 is return, an errors, a errno in what
 
1777
 * went wrong.
 
1778
 *
 
1779
 * @ingroup ntlm_core
 
1780
 */
 
1781
 
 
1782
void
 
1783
heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16],
 
1784
                            const unsigned char *clnt_nonce, size_t clnt_nonce_length,
 
1785
                            const unsigned char svr_chal[8],
 
1786
                            unsigned char derivedkey[16])
 
1787
{
 
1788
    unsigned int hmaclen;
 
1789
    HMAC_CTX c;
 
1790
 
 
1791
    /* HMAC(Ksession, serverchallenge || clientchallenge) */
 
1792
    HMAC_CTX_init(&c);
 
1793
    HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL);
 
1794
    HMAC_Update(&c, svr_chal, 8);
 
1795
    HMAC_Update(&c, clnt_nonce, clnt_nonce_length);
 
1796
    HMAC_Final(&c, derivedkey, &hmaclen);
 
1797
    HMAC_CTX_cleanup(&c);
 
1798
}
 
1799