Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
3 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/heimdal/lib/ntlm/heimntlm.h

    r414 r745  
    4747
    4848#define NTLM_NEG_UNICODE                0x00000001
     49#define NTLM_NEG_OEM                    0x00000002
    4950#define NTLM_NEG_TARGET                 0x00000004
     51#define NTLM_MBZ9                       0x00000008
     52
    5053#define NTLM_NEG_SIGN                   0x00000010
    5154#define NTLM_NEG_SEAL                   0x00000020
     55#define NTLM_NEG_DATAGRAM               0x00000040
     56#define NTLM_NEG_LM_KEY                 0x00000080
    5257#define NTLM_NEG_NTLM                   0x00000200
     58#define NTLM_NEG_ANONYMOUS              0x00000800
    5359
    54 #define NTLM_SUPPLIED_DOMAIN            0x00001000
    55 #define NTLM_SUPPLIED_WORKSTAION        0x00002000
     60#define NTLM_MBZ8                       0x00000100
     61#define NTLM_NEG_NTLM                   0x00000200
     62#define NTLM_NEG_NT_ONLY                0x00000400
     63#define NTLM_MBZ7                       0x00000800 /* anon ? */
    5664
     65#define NTLM_OEM_SUPPLIED_DOMAIN        0x00001000
     66#define NTLM_OEM_SUPPLIED_WORKSTATION   0x00002000
     67#define NTLM_MBZ6                       0x00004000 /* local call ? */
    5768#define NTLM_NEG_ALWAYS_SIGN            0x00008000
    58 #define NTLM_NEG_NTLM2_SESSION          0x00080000
    5969
    6070#define NTLM_TARGET_DOMAIN              0x00010000
    6171#define NTLM_TARGET_SERVER              0x00020000
     72
     73#define NTLM_TARGET_SHARE               0x00040000
     74#define NTLM_NEG_NTLM2_SESSION          0x00080000
     75#define NTLM_NEG_NTLM2                  0x00080000
     76
     77#define NTLM_NEG_IDENTIFY               0x00100000
     78#define NTLM_MBZ5                       0x00200000
     79#define NTLM_NON_NT_SESSION_KEY         0x00400000
     80#define NTLM_NEG_TARGET_INFO            0x00800000
     81
     82#define NTLM_MBZ4                       0x01000000
     83#define NTLM_NEG_VERSION                0x02000000
     84#define NTLM_MBZ3                       0x04000000
     85#define NTLM_MBZ2                       0x08000000
     86
     87#define NTLM_MBZ1                       0x10000000
    6288#define NTLM_ENC_128                    0x20000000
    6389#define NTLM_NEG_KEYEX                  0x40000000
     90#define NTLM_ENC_56                     0x80000000
    6491
    6592/**
     
    6895 * heim_ntlm_free_targetinfo().
    6996 */
     97
     98#define NTLM_TI_AV_FLAG_GUEST           0x00000001
     99
    70100struct ntlm_targetinfo {
    71101    char *servername; /**< */
     
    73103    char *dnsdomainname; /**< */
    74104    char *dnsservername; /**< */
     105    char *dnstreename; /**< */
     106    uint32_t avflags; /**< */
    75107};
    76108
     
    98130    char *targetname; /**< */
    99131    struct ntlm_buf targetinfo; /**< */
    100     unsigned char challange[8]; /**< */
     132    unsigned char challenge[8]; /**< */
    101133    uint32_t context[2]; /**< */
    102134    uint32_t os[2]; /**< */
     
    120152};
    121153
     154#include <ntlm_err.h>
    122155#include <heimntlm-protos.h>
    123156
  • trunk/server/source4/heimdal/lib/ntlm/ntlm.c

    r414 r745  
    33 * (Royal Institute of Technology, Stockholm, Sweden).
    44 * All rights reserved.
     5 *
     6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
    57 *
    68 * Redistribution and use in source and binary forms, with or without
     
    4244#include <limits.h>
    4345
     46#include <roken.h>
     47#include <parse_units.h>
    4448#include <krb5.h>
    45 #include <roken.h>
    4649
    4750#define HC_DEPRECATED_CRYPTO
     
    106109
    107110#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
     115static 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
     153size_t
     154heim_ntlm_unparse_flags(uint32_t flags, char *s, size_t len)
     155{
     156    return unparse_flags(flags, ntlm_flag_units, s, len);
     157}
     158
    109159
    110160/**
     
    198248}
    199249
     250/*
     251 *
     252 */
     253
    200254static krb5_error_code
    201 ret_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s)
     255ret_string(krb5_storage *sp, int ucs2, size_t len, char **s)
    202256{
    203257    krb5_error_code ret;
    204258
    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';
    209265
    210266    if (ucs2) {
    211267        size_t i;
    212         for (i = 0; i < desc->length / 2; i++) {
     268        for (i = 0; i < len / 2; i++) {
    213269            (*s)[i] = (*s)[i * 2];
    214270            if ((*s)[i * 2 + 1]) {
     
    221277    }
    222278    ret = 0;
    223 out:
    224     return ret;
    225 
    226     return 0;
     279 out:
     280    return ret;
     281}
     282
     283
     284
     285static krb5_error_code
     286ret_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;
    227293}
    228294
     
    293359    free(ti->dnsdomainname);
    294360    free(ti->dnsservername);
     361    free(ti->dnstreename);
    295362    memset(ti, 0, sizeof(*ti));
    296363}
    297364
    298365static int
    299 encode_ti_blob(krb5_storage *out, uint16_t type, int ucs2, char *s)
     366encode_ti_string(krb5_storage *out, uint16_t type, int ucs2, char *s)
    300367{
    301368    krb5_error_code ret;
     
    311378 *
    312379 * @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
    314381 * @param data is the return buffer with the encoded message, should be
    315382 * freed with heim_ntlm_free_buf().
     
    336403        return ENOMEM;
    337404
     405    krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE);
     406
    338407    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);
    340409    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);
    342411    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);
    344413    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    }
    346422
    347423    /* end tag */
     
    378454                            struct ntlm_targetinfo *ti)
    379455{
     456    uint16_t type, len;
     457    krb5_storage *in;
     458    int ret = 0, done = 0;
     459
    380460    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;
    382505}
    383506
     
    413536    in = krb5_storage_from_readonly_mem(buf->data, buf->length);
    414537    if (in == NULL) {
    415         ret = EINVAL;
     538        ret = ENOMEM;
    416539        goto out;
    417540    }
     
    423546    CHECK(type, 1);
    424547    CHECK(krb5_ret_uint32(in, &data->flags), 0);
    425     if (data->flags & NTLM_SUPPLIED_DOMAIN)
     548    if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN)
    426549        CHECK(ret_sec_buffer(in, &domain), 0);
    427     if (data->flags & NTLM_SUPPLIED_WORKSTAION)
     550    if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION)
    428551        CHECK(ret_sec_buffer(in, &hostname), 0);
    429552#if 0
     
    433556    }
    434557#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);
    439562
    440563out:
     
    473596    if (type1->domain) {
    474597        base += 8;
    475         flags |= NTLM_SUPPLIED_DOMAIN;
     598        flags |= NTLM_OEM_SUPPLIED_DOMAIN;
    476599    }
    477600    if (type1->hostname) {
    478601        base += 8;
    479         flags |= NTLM_SUPPLIED_WORKSTAION;
     602        flags |= NTLM_OEM_SUPPLIED_WORKSTATION;
    480603    }
    481604    if (type1->os[0])
    482605        base += 8;
    483606
     607    domain.offset = base;
    484608    if (type1->domain) {
    485         domain.offset = base;
    486609        domain.length = len_string(0, type1->domain);
    487610        domain.allocated = domain.length;
    488     }
     611    } else {
     612        domain.length = 0;
     613        domain.allocated = 0;
     614    }
     615
     616    hostname.offset = domain.allocated + domain.offset;
    489617    if (type1->hostname) {
    490         hostname.offset = domain.allocated + domain.offset;
    491618        hostname.length = len_string(0, type1->hostname);
    492619        hostname.allocated = hostname.length;
     620    } else {
     621        hostname.length = 0;
     622        hostname.allocated = 0;
    493623    }
    494624
     
    503633    CHECK(krb5_store_uint32(out, flags), 0);
    504634
    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
    510638        CHECK(krb5_store_uint32(out, type1->os[0]), 0);
    511639        CHECK(krb5_store_uint32(out, type1->os[1]), 0);
    512     }
     640#endif
    513641    if (type1->domain)
    514642        CHECK(put_string(out, 0, type1->domain), 0);
     
    559687    in = krb5_storage_from_readonly_mem(buf->data, buf->length);
    560688    if (in == NULL) {
    561         ret = EINVAL;
     689        ret = ENOMEM;
    562690        goto out;
    563691    }
     
    573701    if (type2->flags & NTLM_NEG_UNICODE)
    574702        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));
    577705    CHECK(krb5_ret_uint32(in, &ctx[0]), 0); /* context */
    578706    CHECK(krb5_ret_uint32(in, &ctx[1]), 0);
    579707    CHECK(ret_sec_buffer(in, &targetinfo), 0);
    580708    /* 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
    585 
    586     CHECK(ret_string(in, ucs2, &targetname, &type2->targetname), 0);
     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    }
     713
     714    CHECK(ret_sec_string(in, ucs2, &targetname, &type2->targetname), 0);
    587715    CHECK(ret_buf(in, &targetinfo, &type2->targetinfo), 0);
    588716    ret = 0;
     
    619747    int ucs2 = 0;
    620748
    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;
    625753
    626754    if (type2->flags & NTLM_NEG_UNICODE)
     
    645773    CHECK(store_sec_buffer(out, &targetname), 0);
    646774    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));
    649777    CHECK(krb5_store_uint32(out, 0), 0); /* context */
    650778    CHECK(krb5_store_uint32(out, 0), 0);
    651779    CHECK(store_sec_buffer(out, &targetinfo), 0);
    652780    /* os version */
    653     if (type2->os[0]) {
     781    if (type2->flags & NTLM_NEG_VERSION) {
    654782        CHECK(krb5_store_uint32(out, type2->os[0]), 0);
    655783        CHECK(krb5_store_uint32(out, type2->os[1]), 0);
     
    710838    krb5_storage *in;
    711839    struct sec_buffer lm, ntlm, target, username, sessionkey, ws;
     840    uint32_t min_offset = 72;
    712841
    713842    memset(type3, 0, sizeof(*type3));
     
    716845    in = krb5_storage_from_readonly_mem(buf->data, buf->length);
    717846    if (in == NULL) {
    718         ret = EINVAL;
     847        ret = ENOMEM;
    719848        goto out;
    720849    }
     
    726855    CHECK(type, 3);
    727856    CHECK(ret_sec_buffer(in, &lm), 0);
     857    if (lm.allocated)
     858        min_offset = min(min_offset, lm.offset);
    728859    CHECK(ret_sec_buffer(in, &ntlm), 0);
     860    if (ntlm.allocated)
     861        min_offset = min(min_offset, ntlm.offset);
    729862    CHECK(ret_sec_buffer(in, &target), 0);
     863    if (target.allocated)
     864        min_offset = min(min_offset, target.offset);
    730865    CHECK(ret_sec_buffer(in, &username), 0);
     866    if (username.allocated)
     867        min_offset = min(min_offset, username.offset);
    731868    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) {
    733873        CHECK(ret_sec_buffer(in, &sessionkey), 0);
    734     }
    735     if (lm.offset >= 64) {
     874        min_offset = max(min_offset, sessionkey.offset);
    736875        CHECK(krb5_ret_uint32(in, &type3->flags), 0);
    737876    }
    738     if (lm.offset >= 72) {
     877    if (min_offset > 52 + 8 + 4 + 8) {
    739878        CHECK(krb5_ret_uint32(in, &type3->os[0]), 0);
    740879        CHECK(krb5_ret_uint32(in, &type3->os[1]), 0);
     
    742881    CHECK(ret_buf(in, &lm, &type3->lm), 0);
    743882    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);
    747886    if (sessionkey.offset)
    748887        CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0);
     
    787926
    788927    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
    793932    if (type3->os[0]) {
    794933        base += 8;
     
    798937        ucs2 = 1;
    799938
    800     lm.offset = base;
     939    target.offset = base;
     940    target.length = len_string(ucs2, type3->targetname);
     941    target.allocated = target.length;
     942
     943    username.offset = target.offset + target.allocated;
     944    username.length = len_string(ucs2, type3->username);
     945    username.allocated = username.length;
     946
     947    ws.offset = username.offset + username.allocated;
     948    ws.length = len_string(ucs2, type3->ws);
     949    ws.allocated = ws.length;
     950
     951    lm.offset = ws.offset + ws.allocated;
    801952    lm.length = type3->lm.length;
    802953    lm.allocated = type3->lm.length;
     
    806957    ntlm.allocated = ntlm.length;
    807958
    808     target.offset = ntlm.offset + ntlm.allocated;
    809     target.length = len_string(ucs2, type3->targetname);
    810     target.allocated = target.length;
    811 
    812     username.offset = target.offset + target.allocated;
    813     username.length = len_string(ucs2, type3->username);
    814     username.allocated = username.length;
    815 
    816     ws.offset = username.offset + username.allocated;
    817     ws.length = len_string(ucs2, type3->ws);
    818     ws.allocated = ws.length;
    819 
    820     sessionkey.offset = ws.offset + ws.allocated;
     959    sessionkey.offset = ntlm.offset + ntlm.allocated;
    821960    sessionkey.length = type3->sessionkey.length;
    822961    sessionkey.allocated = type3->sessionkey.length;
     
    836975    CHECK(store_sec_buffer(out, &username), 0);
    837976    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
    843980#if 0
    844981    CHECK(krb5_store_uint32(out, 0), 0); /* os0 */
     
    846983#endif
    847984
    848     CHECK(put_buf(out, &type3->lm), 0);
    849     CHECK(put_buf(out, &type3->ntlm), 0);
    850985    CHECK(put_string(out, ucs2, type3->targetname), 0);
    851986    CHECK(put_string(out, ucs2, type3->username), 0);
    852987    CHECK(put_string(out, ucs2, type3->ws), 0);
     988    CHECK(put_buf(out, &type3->lm), 0);
     989    CHECK(put_buf(out, &type3->ntlm), 0);
    853990    CHECK(put_buf(out, &type3->sessionkey), 0);
    854991
     
    8731010static void
    8741011splitandenc(unsigned char *hash,
    875             unsigned char *challange,
     1012            unsigned char *challenge,
    8761013            unsigned char *answer)
    8771014{
    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);
    8941032    memset(key, 0, sizeof(key));
    8951033}
     
    9111049{
    9121050    struct ntlm_buf buf;
    913     MD4_CTX ctx;
     1051    EVP_MD_CTX *m;
    9141052    int ret;
    9151053
     
    9241062        return ret;
    9251063    }
    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
    9291077    heim_ntlm_free_buf(&buf);
    9301078    return 0;
     
    9361084 * @param key the ntlm v1 key
    9371085 * @param len length of key
    938  * @param challange sent by the server
     1086 * @param challenge sent by the server
    9391087 * @param answer calculated answer, should be freed with heim_ntlm_free_buf().
    9401088 *
     
    9471095int
    9481096heim_ntlm_calculate_ntlm1(void *key, size_t len,
    949                           unsigned char challange[8],
     1097                          unsigned char challenge[8],
    9501098                          struct ntlm_buf *answer)
    9511099{
     
    9531101
    9541102    if (len != MD4_DIGEST_LENGTH)
    955         return EINVAL;
     1103        return HNTLM_ERR_INVALID_LENGTH;
    9561104
    9571105    memcpy(res, key, len);
     
    9631111    answer->length = 24;
    9641112
    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);
     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);
    9681116
    9691117    return 0;
    9701118}
     1119
     1120int
     1121heim_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
     1146int
     1147heim_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
     1173int
     1174heim_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
    9711222
    9721223/**
     
    9891240                             struct ntlm_buf *master)
    9901241{
    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
     1271int
     1272heim_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
     1303int
     1304heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey,
     1305                       struct ntlm_buf *encryptedSession,
     1306                       struct ntlm_buf *session)
     1307{
     1308    EVP_CIPHER_CTX c;
     1309
    9941310    memset(session, 0, sizeof(*session));
    9951311
    996     if (len != MD4_DIGEST_LENGTH)
    997         return EINVAL;
     1312    if (baseKey->length != MD4_DIGEST_LENGTH)
     1313        return HNTLM_ERR_INVALID_LENGTH;
    9981314
    9991315    session->length = MD4_DIGEST_LENGTH;
     
    10011317    if (session->data == NULL) {
    10021318        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);
     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);
    10091325        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));
     1326        return HNTLM_ERR_CRYPTO;
     1327    }
     1328
     1329    EVP_Cipher(&c, session->data, encryptedSession->data, session->length);
     1330    EVP_CIPHER_CTX_cleanup(&c);
    10321331
    10331332    return 0;
    10341333}
     1334
    10351335
    10361336/**
     
    11051405}
    11061406
    1107 
    1108 /**
    1109  * Calculate NTLMv2 response
     1407/**
     1408 * Calculate LMv2 response
    11101409 *
    11111410 * @param key the ntlm key
     
    11131412 * @param username name of the user, as sent in the message, assumed to be in UTF8.
    11141413 * @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.
     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
     1424int
     1425heim_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
     1454
     1455/**
     1456 * Calculate NTLMv2 response
     1457 *
     1458 * @param key the ntlm key
     1459 * @param len length of key
     1460 * @param username name of the user, as sent in the message, assumed to be in UTF8.
     1461 * @param target the name of the target, assumed to be in UTF8.
     1462 * @param serverchallenge challenge as sent by the server in the type2 message.
    11161463 * @param infotarget infotarget as sent by the server in the type2 message.
    11171464 * @param ntlmv2 calculated session key
     
    11281475                          const char *username,
    11291476                          const char *target,
    1130                           const unsigned char serverchallange[8],
     1477                          const unsigned char serverchallenge[8],
    11311478                          const struct ntlm_buf *infotarget,
    11321479                          unsigned char ntlmv2[16],
     
    11351482    krb5_error_code ret;
    11361483    krb5_data data;
    1137     unsigned int hmaclen;
    11381484    unsigned char ntlmv2answer[16];
    11391485    krb5_storage *sp;
    1140     unsigned char clientchallange[8];
    1141     HMAC_CTX c;
     1486    unsigned char clientchallenge[8];
    11421487    uint64_t t;
    11431488
    11441489    t = unix2nttime(time(NULL));
    11451490
    1146     if (RAND_bytes(clientchallange, sizeof(clientchallange)) != 1)
    1147         return EINVAL;
     1491    if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1)
     1492        return HNTLM_ERR_RAND;
    11481493
    11491494    /* calculate ntlmv2 key */
     
    11641509    CHECK(krb5_store_uint32(sp, t >> 32), 0);
    11651510
    1166     CHECK(krb5_storage_write(sp, clientchallange, 8), 8);
     1511    CHECK(krb5_storage_write(sp, clientchallenge, 8), 8);
    11671512
    11681513    CHECK(krb5_store_uint32(sp, 0), 0);  /* unknown but zero will work */
     
    11751520    sp = NULL;
    11761521
    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);
    11831523
    11841524    sp = krb5_storage_emem();
     
    12161556 * @param target the name of the target, assumed to be in UTF8.
    12171557 * @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.
    12191559 * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf().
    12201560 * @param infotarget infotarget as sent by the server in the type2 message.
     
    12321572                       const char *target,
    12331573                       time_t now,
    1234                        const unsigned char serverchallange[8],
     1574                       const unsigned char serverchallenge[8],
    12351575                       const struct ntlm_buf *answer,
    12361576                       struct ntlm_buf *infotarget,
     
    12381578{
    12391579    krb5_error_code ret;
    1240     unsigned int hmaclen;
    12411580    unsigned char clientanswer[16];
    12421581    unsigned char clientnonce[8];
    12431582    unsigned char serveranswer[16];
    12441583    krb5_storage *sp;
    1245     HMAC_CTX c;
    1246     uint64_t t;
    12471584    time_t authtime;
    12481585    uint32_t temp;
     1586    uint64_t t;
    12491587
    12501588    infotarget->length = 0;
     
    12521590
    12531591    if (answer->length < 16)
    1254         return EINVAL;
     1592        return HNTLM_ERR_INVALID_LENGTH;
    12551593
    12561594    if (now == 0)
     
    12831621
    12841622    if (abs((int)(authtime - now)) > authtimediff) {
    1285         ret = EINVAL;
     1623        ret = HNTLM_ERR_TIME_SKEW;
    12861624        goto out;
    12871625    }
    12881626
    1289     /* client challange */
     1627    /* client challenge */
    12901628    CHECK(krb5_storage_read(sp, clientnonce, 8), 8);
    12911629
     
    13051643    sp = NULL;
    13061644
    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);
    13131654
    13141655    if (memcmp(serveranswer, clientanswer, 16) != 0) {
    13151656        heim_ntlm_free_buf(infotarget);
    1316         return EINVAL;
     1657        return HNTLM_ERR_AUTH;
    13171658    }
    13181659
     
    13481689                               struct ntlm_buf *ntlm)
    13491690{
    1350     unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
     1691    unsigned char ntlm2_sess_hash[8];
    13511692    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    }
    13531700
    13541701    lm->data = malloc(24);
    1355     if (lm->data == NULL)
    1356         return ENOMEM;
     1702    if (lm->data == NULL) {
     1703        return ENOMEM;
     1704    }
    13571705    lm->length = 24;
    13581706
     
    13691717    memcpy(lm->data, clnt_nonce, 8);
    13701718
    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 
    13761719    memset(res, 0, sizeof(res));
    13771720    memcpy(res, ntlm_hash, 16);
     
    13841727    return 0;
    13851728}
     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
     1744int
     1745heim_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
     1782void
     1783heim_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
Note: See TracChangeset for help on using the changeset viewer.