1178825Sdfr/* 2233294Sstas * Copyright (c) 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "krb5_locl.h" 35178825Sdfr#include "digest_asn1.h" 36178825Sdfr 37233294Sstas#ifndef HEIMDAL_SMALLER 38233294Sstas 39178825Sdfrstruct krb5_digest_data { 40178825Sdfr char *cbtype; 41178825Sdfr char *cbbinding; 42178825Sdfr 43178825Sdfr DigestInit init; 44178825Sdfr DigestInitReply initReply; 45178825Sdfr DigestRequest request; 46178825Sdfr DigestResponse response; 47178825Sdfr}; 48178825Sdfr 49233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 50178825Sdfrkrb5_digest_alloc(krb5_context context, krb5_digest *digest) 51178825Sdfr{ 52178825Sdfr krb5_digest d; 53178825Sdfr 54178825Sdfr d = calloc(1, sizeof(*d)); 55178825Sdfr if (d == NULL) { 56178825Sdfr *digest = NULL; 57233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 58178825Sdfr return ENOMEM; 59178825Sdfr } 60178825Sdfr *digest = d; 61178825Sdfr 62178825Sdfr return 0; 63178825Sdfr} 64178825Sdfr 65233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 66178825Sdfrkrb5_digest_free(krb5_digest digest) 67178825Sdfr{ 68178825Sdfr if (digest == NULL) 69178825Sdfr return; 70178825Sdfr free_DigestInit(&digest->init); 71178825Sdfr free_DigestInitReply(&digest->initReply); 72178825Sdfr free_DigestRequest(&digest->request); 73178825Sdfr free_DigestResponse(&digest->response); 74178825Sdfr memset(digest, 0, sizeof(*digest)); 75178825Sdfr free(digest); 76178825Sdfr return; 77178825Sdfr} 78178825Sdfr 79233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 80178825Sdfrkrb5_digest_set_server_cb(krb5_context context, 81178825Sdfr krb5_digest digest, 82178825Sdfr const char *type, 83178825Sdfr const char *binding) 84178825Sdfr{ 85178825Sdfr if (digest->init.channel) { 86233294Sstas krb5_set_error_message(context, EINVAL, 87233294Sstas N_("server channel binding already set", "")); 88178825Sdfr return EINVAL; 89178825Sdfr } 90178825Sdfr digest->init.channel = calloc(1, sizeof(*digest->init.channel)); 91178825Sdfr if (digest->init.channel == NULL) 92178825Sdfr goto error; 93178825Sdfr 94178825Sdfr digest->init.channel->cb_type = strdup(type); 95178825Sdfr if (digest->init.channel->cb_type == NULL) 96178825Sdfr goto error; 97178825Sdfr 98178825Sdfr digest->init.channel->cb_binding = strdup(binding); 99233294Sstas if (digest->init.channel->cb_binding == NULL) 100178825Sdfr goto error; 101178825Sdfr return 0; 102233294Sstas error: 103178825Sdfr if (digest->init.channel) { 104178825Sdfr free(digest->init.channel->cb_type); 105178825Sdfr free(digest->init.channel->cb_binding); 106178825Sdfr free(digest->init.channel); 107178825Sdfr digest->init.channel = NULL; 108178825Sdfr } 109233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 110178825Sdfr return ENOMEM; 111178825Sdfr} 112178825Sdfr 113233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 114178825Sdfrkrb5_digest_set_type(krb5_context context, 115178825Sdfr krb5_digest digest, 116178825Sdfr const char *type) 117178825Sdfr{ 118178825Sdfr if (digest->init.type) { 119233294Sstas krb5_set_error_message(context, EINVAL, "client type already set"); 120178825Sdfr return EINVAL; 121178825Sdfr } 122178825Sdfr digest->init.type = strdup(type); 123178825Sdfr if (digest->init.type == NULL) { 124233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 125178825Sdfr return ENOMEM; 126178825Sdfr } 127178825Sdfr return 0; 128178825Sdfr} 129178825Sdfr 130233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 131178825Sdfrkrb5_digest_set_hostname(krb5_context context, 132178825Sdfr krb5_digest digest, 133178825Sdfr const char *hostname) 134178825Sdfr{ 135178825Sdfr if (digest->init.hostname) { 136233294Sstas krb5_set_error_message(context, EINVAL, "server hostname already set"); 137178825Sdfr return EINVAL; 138178825Sdfr } 139178825Sdfr digest->init.hostname = malloc(sizeof(*digest->init.hostname)); 140178825Sdfr if (digest->init.hostname == NULL) { 141233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 142178825Sdfr return ENOMEM; 143178825Sdfr } 144178825Sdfr *digest->init.hostname = strdup(hostname); 145178825Sdfr if (*digest->init.hostname == NULL) { 146233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 147178825Sdfr free(digest->init.hostname); 148178825Sdfr digest->init.hostname = NULL; 149178825Sdfr return ENOMEM; 150178825Sdfr } 151178825Sdfr return 0; 152178825Sdfr} 153178825Sdfr 154233294SstasKRB5_LIB_FUNCTION const char * KRB5_LIB_CALL 155178825Sdfrkrb5_digest_get_server_nonce(krb5_context context, 156178825Sdfr krb5_digest digest) 157178825Sdfr{ 158178825Sdfr return digest->initReply.nonce; 159178825Sdfr} 160178825Sdfr 161233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 162178825Sdfrkrb5_digest_set_server_nonce(krb5_context context, 163178825Sdfr krb5_digest digest, 164178825Sdfr const char *nonce) 165178825Sdfr{ 166178825Sdfr if (digest->request.serverNonce) { 167233294Sstas krb5_set_error_message(context, EINVAL, N_("nonce already set", "")); 168178825Sdfr return EINVAL; 169178825Sdfr } 170178825Sdfr digest->request.serverNonce = strdup(nonce); 171178825Sdfr if (digest->request.serverNonce == NULL) { 172233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 173178825Sdfr return ENOMEM; 174178825Sdfr } 175178825Sdfr return 0; 176178825Sdfr} 177178825Sdfr 178233294SstasKRB5_LIB_FUNCTION const char * KRB5_LIB_CALL 179178825Sdfrkrb5_digest_get_opaque(krb5_context context, 180178825Sdfr krb5_digest digest) 181178825Sdfr{ 182178825Sdfr return digest->initReply.opaque; 183178825Sdfr} 184178825Sdfr 185233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 186178825Sdfrkrb5_digest_set_opaque(krb5_context context, 187178825Sdfr krb5_digest digest, 188178825Sdfr const char *opaque) 189178825Sdfr{ 190178825Sdfr if (digest->request.opaque) { 191233294Sstas krb5_set_error_message(context, EINVAL, "opaque already set"); 192178825Sdfr return EINVAL; 193178825Sdfr } 194178825Sdfr digest->request.opaque = strdup(opaque); 195178825Sdfr if (digest->request.opaque == NULL) { 196233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 197178825Sdfr return ENOMEM; 198178825Sdfr } 199178825Sdfr return 0; 200178825Sdfr} 201178825Sdfr 202233294SstasKRB5_LIB_FUNCTION const char * KRB5_LIB_CALL 203178825Sdfrkrb5_digest_get_identifier(krb5_context context, 204178825Sdfr krb5_digest digest) 205178825Sdfr{ 206178825Sdfr if (digest->initReply.identifier == NULL) 207178825Sdfr return NULL; 208178825Sdfr return *digest->initReply.identifier; 209178825Sdfr} 210178825Sdfr 211233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 212178825Sdfrkrb5_digest_set_identifier(krb5_context context, 213178825Sdfr krb5_digest digest, 214178825Sdfr const char *id) 215178825Sdfr{ 216178825Sdfr if (digest->request.identifier) { 217233294Sstas krb5_set_error_message(context, EINVAL, N_("identifier already set", "")); 218178825Sdfr return EINVAL; 219178825Sdfr } 220178825Sdfr digest->request.identifier = calloc(1, sizeof(*digest->request.identifier)); 221178825Sdfr if (digest->request.identifier == NULL) { 222233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 223178825Sdfr return ENOMEM; 224178825Sdfr } 225178825Sdfr *digest->request.identifier = strdup(id); 226178825Sdfr if (*digest->request.identifier == NULL) { 227233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 228178825Sdfr free(digest->request.identifier); 229178825Sdfr digest->request.identifier = NULL; 230178825Sdfr return ENOMEM; 231178825Sdfr } 232178825Sdfr return 0; 233178825Sdfr} 234178825Sdfr 235178825Sdfrstatic krb5_error_code 236178825Sdfrdigest_request(krb5_context context, 237178825Sdfr krb5_realm realm, 238178825Sdfr krb5_ccache ccache, 239178825Sdfr krb5_key_usage usage, 240178825Sdfr const DigestReqInner *ireq, 241178825Sdfr DigestRepInner *irep) 242178825Sdfr{ 243178825Sdfr DigestREQ req; 244178825Sdfr DigestREP rep; 245178825Sdfr krb5_error_code ret; 246178825Sdfr krb5_data data, data2; 247233294Sstas size_t size = 0; 248178825Sdfr krb5_crypto crypto = NULL; 249178825Sdfr krb5_auth_context ac = NULL; 250178825Sdfr krb5_principal principal = NULL; 251178825Sdfr krb5_ccache id = NULL; 252178825Sdfr krb5_realm r = NULL; 253178825Sdfr 254178825Sdfr krb5_data_zero(&data); 255178825Sdfr krb5_data_zero(&data2); 256178825Sdfr memset(&req, 0, sizeof(req)); 257178825Sdfr memset(&rep, 0, sizeof(rep)); 258178825Sdfr 259178825Sdfr if (ccache == NULL) { 260178825Sdfr ret = krb5_cc_default(context, &id); 261178825Sdfr if (ret) 262178825Sdfr goto out; 263178825Sdfr } else 264178825Sdfr id = ccache; 265178825Sdfr 266178825Sdfr if (realm == NULL) { 267178825Sdfr ret = krb5_get_default_realm(context, &r); 268178825Sdfr if (ret) 269178825Sdfr goto out; 270178825Sdfr } else 271178825Sdfr r = realm; 272178825Sdfr 273178825Sdfr /* 274178825Sdfr * 275178825Sdfr */ 276178825Sdfr 277233294Sstas ret = krb5_make_principal(context, &principal, 278178825Sdfr r, KRB5_DIGEST_NAME, r, NULL); 279178825Sdfr if (ret) 280178825Sdfr goto out; 281178825Sdfr 282178825Sdfr ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length, 283178825Sdfr ireq, &size, ret); 284178825Sdfr if (ret) { 285233294Sstas krb5_set_error_message(context, ret, 286233294Sstas N_("Failed to encode digest inner request", "")); 287178825Sdfr goto out; 288178825Sdfr } 289178825Sdfr if (size != data.length) 290178825Sdfr krb5_abortx(context, "ASN.1 internal encoder error"); 291178825Sdfr 292233294Sstas ret = krb5_mk_req_exact(context, &ac, 293178825Sdfr AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED, 294178825Sdfr principal, NULL, id, &req.apReq); 295178825Sdfr if (ret) 296178825Sdfr goto out; 297178825Sdfr 298178825Sdfr { 299178825Sdfr krb5_keyblock *key; 300178825Sdfr 301178825Sdfr ret = krb5_auth_con_getlocalsubkey(context, ac, &key); 302178825Sdfr if (ret) 303178825Sdfr goto out; 304178825Sdfr if (key == NULL) { 305178825Sdfr ret = EINVAL; 306233294Sstas krb5_set_error_message(context, ret, 307233294Sstas N_("Digest failed to get local subkey", "")); 308178825Sdfr goto out; 309178825Sdfr } 310178825Sdfr 311178825Sdfr ret = krb5_crypto_init(context, key, 0, &crypto); 312178825Sdfr krb5_free_keyblock (context, key); 313178825Sdfr if (ret) 314178825Sdfr goto out; 315178825Sdfr } 316178825Sdfr 317178825Sdfr ret = krb5_encrypt_EncryptedData(context, crypto, usage, 318233294Sstas data.data, data.length, 0, 319178825Sdfr &req.innerReq); 320178825Sdfr if (ret) 321178825Sdfr goto out; 322178825Sdfr 323178825Sdfr krb5_data_free(&data); 324178825Sdfr 325178825Sdfr ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length, 326178825Sdfr &req, &size, ret); 327178825Sdfr if (ret) { 328233294Sstas krb5_set_error_message(context, ret, 329233294Sstas N_("Failed to encode DigestREQest", "")); 330178825Sdfr goto out; 331178825Sdfr } 332178825Sdfr if (size != data.length) 333178825Sdfr krb5_abortx(context, "ASN.1 internal encoder error"); 334178825Sdfr 335178825Sdfr ret = krb5_sendto_kdc(context, &data, &r, &data2); 336178825Sdfr if (ret) 337178825Sdfr goto out; 338178825Sdfr 339178825Sdfr ret = decode_DigestREP(data2.data, data2.length, &rep, NULL); 340178825Sdfr if (ret) { 341233294Sstas krb5_set_error_message(context, ret, 342233294Sstas N_("Failed to parse digest response", "")); 343178825Sdfr goto out; 344178825Sdfr } 345178825Sdfr 346178825Sdfr { 347178825Sdfr krb5_ap_rep_enc_part *repl; 348178825Sdfr 349178825Sdfr ret = krb5_rd_rep(context, ac, &rep.apRep, &repl); 350178825Sdfr if (ret) 351178825Sdfr goto out; 352178825Sdfr 353178825Sdfr krb5_free_ap_rep_enc_part(context, repl); 354178825Sdfr } 355178825Sdfr { 356178825Sdfr krb5_keyblock *key; 357178825Sdfr 358178825Sdfr ret = krb5_auth_con_getremotesubkey(context, ac, &key); 359178825Sdfr if (ret) 360178825Sdfr goto out; 361178825Sdfr if (key == NULL) { 362178825Sdfr ret = EINVAL; 363233294Sstas krb5_set_error_message(context, ret, 364233294Sstas N_("Digest reply have no remote subkey", "")); 365178825Sdfr goto out; 366178825Sdfr } 367178825Sdfr 368178825Sdfr krb5_crypto_destroy(context, crypto); 369178825Sdfr ret = krb5_crypto_init(context, key, 0, &crypto); 370178825Sdfr krb5_free_keyblock (context, key); 371178825Sdfr if (ret) 372178825Sdfr goto out; 373178825Sdfr } 374178825Sdfr 375178825Sdfr krb5_data_free(&data); 376178825Sdfr ret = krb5_decrypt_EncryptedData(context, crypto, usage, 377178825Sdfr &rep.innerRep, &data); 378178825Sdfr if (ret) 379178825Sdfr goto out; 380233294Sstas 381178825Sdfr ret = decode_DigestRepInner(data.data, data.length, irep, NULL); 382178825Sdfr if (ret) { 383233294Sstas krb5_set_error_message(context, ret, 384233294Sstas N_("Failed to decode digest inner reply", "")); 385178825Sdfr goto out; 386178825Sdfr } 387178825Sdfr 388233294Sstas out: 389178825Sdfr if (ccache == NULL && id) 390178825Sdfr krb5_cc_close(context, id); 391178825Sdfr if (realm == NULL && r) 392178825Sdfr free(r); 393178825Sdfr if (crypto) 394178825Sdfr krb5_crypto_destroy(context, crypto); 395178825Sdfr if (ac) 396178825Sdfr krb5_auth_con_free(context, ac); 397178825Sdfr if (principal) 398178825Sdfr krb5_free_principal(context, principal); 399178825Sdfr 400178825Sdfr krb5_data_free(&data); 401178825Sdfr krb5_data_free(&data2); 402178825Sdfr 403178825Sdfr free_DigestREQ(&req); 404178825Sdfr free_DigestREP(&rep); 405178825Sdfr 406178825Sdfr return ret; 407178825Sdfr} 408178825Sdfr 409233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 410178825Sdfrkrb5_digest_init_request(krb5_context context, 411178825Sdfr krb5_digest digest, 412178825Sdfr krb5_realm realm, 413178825Sdfr krb5_ccache ccache) 414178825Sdfr{ 415178825Sdfr DigestReqInner ireq; 416178825Sdfr DigestRepInner irep; 417178825Sdfr krb5_error_code ret; 418178825Sdfr 419178825Sdfr memset(&ireq, 0, sizeof(ireq)); 420178825Sdfr memset(&irep, 0, sizeof(irep)); 421178825Sdfr 422178825Sdfr if (digest->init.type == NULL) { 423233294Sstas krb5_set_error_message(context, EINVAL, 424233294Sstas N_("Type missing from init req", "")); 425178825Sdfr return EINVAL; 426178825Sdfr } 427178825Sdfr 428178825Sdfr ireq.element = choice_DigestReqInner_init; 429178825Sdfr ireq.u.init = digest->init; 430178825Sdfr 431178825Sdfr ret = digest_request(context, realm, ccache, 432178825Sdfr KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 433178825Sdfr if (ret) 434178825Sdfr goto out; 435178825Sdfr 436178825Sdfr if (irep.element == choice_DigestRepInner_error) { 437178825Sdfr ret = irep.u.error.code; 438233294Sstas krb5_set_error_message(context, ret, N_("Digest init error: %s", ""), 439233294Sstas irep.u.error.reason); 440178825Sdfr goto out; 441178825Sdfr } 442178825Sdfr 443178825Sdfr if (irep.element != choice_DigestRepInner_initReply) { 444178825Sdfr ret = EINVAL; 445233294Sstas krb5_set_error_message(context, ret, 446233294Sstas N_("digest reply not an initReply", "")); 447178825Sdfr goto out; 448178825Sdfr } 449178825Sdfr 450178825Sdfr ret = copy_DigestInitReply(&irep.u.initReply, &digest->initReply); 451178825Sdfr if (ret) { 452233294Sstas krb5_set_error_message(context, ret, 453233294Sstas N_("Failed to copy initReply", "")); 454178825Sdfr goto out; 455178825Sdfr } 456178825Sdfr 457233294Sstas out: 458178825Sdfr free_DigestRepInner(&irep); 459178825Sdfr 460178825Sdfr return ret; 461178825Sdfr} 462178825Sdfr 463178825Sdfr 464233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 465178825Sdfrkrb5_digest_set_client_nonce(krb5_context context, 466178825Sdfr krb5_digest digest, 467178825Sdfr const char *nonce) 468178825Sdfr{ 469178825Sdfr if (digest->request.clientNonce) { 470233294Sstas krb5_set_error_message(context, EINVAL, 471233294Sstas N_("clientNonce already set", "")); 472178825Sdfr return EINVAL; 473178825Sdfr } 474233294Sstas digest->request.clientNonce = 475178825Sdfr calloc(1, sizeof(*digest->request.clientNonce)); 476178825Sdfr if (digest->request.clientNonce == NULL) { 477233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 478178825Sdfr return ENOMEM; 479178825Sdfr } 480178825Sdfr *digest->request.clientNonce = strdup(nonce); 481178825Sdfr if (*digest->request.clientNonce == NULL) { 482233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 483178825Sdfr free(digest->request.clientNonce); 484178825Sdfr digest->request.clientNonce = NULL; 485178825Sdfr return ENOMEM; 486178825Sdfr } 487178825Sdfr return 0; 488178825Sdfr} 489178825Sdfr 490233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 491178825Sdfrkrb5_digest_set_digest(krb5_context context, 492178825Sdfr krb5_digest digest, 493178825Sdfr const char *dgst) 494178825Sdfr{ 495178825Sdfr if (digest->request.digest) { 496233294Sstas krb5_set_error_message(context, EINVAL, 497233294Sstas N_("digest already set", "")); 498178825Sdfr return EINVAL; 499178825Sdfr } 500178825Sdfr digest->request.digest = strdup(dgst); 501178825Sdfr if (digest->request.digest == NULL) { 502233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 503178825Sdfr return ENOMEM; 504178825Sdfr } 505178825Sdfr return 0; 506178825Sdfr} 507178825Sdfr 508233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 509178825Sdfrkrb5_digest_set_username(krb5_context context, 510178825Sdfr krb5_digest digest, 511178825Sdfr const char *username) 512178825Sdfr{ 513178825Sdfr if (digest->request.username) { 514233294Sstas krb5_set_error_message(context, EINVAL, "username already set"); 515178825Sdfr return EINVAL; 516178825Sdfr } 517178825Sdfr digest->request.username = strdup(username); 518178825Sdfr if (digest->request.username == NULL) { 519233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 520178825Sdfr return ENOMEM; 521178825Sdfr } 522178825Sdfr return 0; 523178825Sdfr} 524178825Sdfr 525233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 526178825Sdfrkrb5_digest_set_authid(krb5_context context, 527178825Sdfr krb5_digest digest, 528178825Sdfr const char *authid) 529178825Sdfr{ 530178825Sdfr if (digest->request.authid) { 531233294Sstas krb5_set_error_message(context, EINVAL, "authid already set"); 532178825Sdfr return EINVAL; 533178825Sdfr } 534178825Sdfr digest->request.authid = malloc(sizeof(*digest->request.authid)); 535178825Sdfr if (digest->request.authid == NULL) { 536233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 537178825Sdfr return ENOMEM; 538178825Sdfr } 539178825Sdfr *digest->request.authid = strdup(authid); 540178825Sdfr if (*digest->request.authid == NULL) { 541233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 542178825Sdfr free(digest->request.authid); 543178825Sdfr digest->request.authid = NULL; 544178825Sdfr return ENOMEM; 545178825Sdfr } 546178825Sdfr return 0; 547178825Sdfr} 548178825Sdfr 549233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 550178825Sdfrkrb5_digest_set_authentication_user(krb5_context context, 551178825Sdfr krb5_digest digest, 552178825Sdfr krb5_principal authentication_user) 553178825Sdfr{ 554178825Sdfr krb5_error_code ret; 555178825Sdfr 556178825Sdfr if (digest->request.authentication_user) { 557233294Sstas krb5_set_error_message(context, EINVAL, 558233294Sstas N_("authentication_user already set", "")); 559178825Sdfr return EINVAL; 560178825Sdfr } 561178825Sdfr ret = krb5_copy_principal(context, 562178825Sdfr authentication_user, 563178825Sdfr &digest->request.authentication_user); 564233294Sstas if (ret) 565233294Sstas return ret; 566178825Sdfr return 0; 567178825Sdfr} 568178825Sdfr 569233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 570178825Sdfrkrb5_digest_set_realm(krb5_context context, 571178825Sdfr krb5_digest digest, 572178825Sdfr const char *realm) 573178825Sdfr{ 574178825Sdfr if (digest->request.realm) { 575233294Sstas krb5_set_error_message(context, EINVAL, "realm already set"); 576178825Sdfr return EINVAL; 577178825Sdfr } 578178825Sdfr digest->request.realm = malloc(sizeof(*digest->request.realm)); 579178825Sdfr if (digest->request.realm == NULL) { 580233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 581178825Sdfr return ENOMEM; 582178825Sdfr } 583178825Sdfr *digest->request.realm = strdup(realm); 584178825Sdfr if (*digest->request.realm == NULL) { 585233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 586178825Sdfr free(digest->request.realm); 587178825Sdfr digest->request.realm = NULL; 588178825Sdfr return ENOMEM; 589178825Sdfr } 590178825Sdfr return 0; 591178825Sdfr} 592178825Sdfr 593233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 594178825Sdfrkrb5_digest_set_method(krb5_context context, 595178825Sdfr krb5_digest digest, 596178825Sdfr const char *method) 597178825Sdfr{ 598178825Sdfr if (digest->request.method) { 599233294Sstas krb5_set_error_message(context, EINVAL, 600233294Sstas N_("method already set", "")); 601178825Sdfr return EINVAL; 602178825Sdfr } 603178825Sdfr digest->request.method = malloc(sizeof(*digest->request.method)); 604178825Sdfr if (digest->request.method == NULL) { 605233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 606178825Sdfr return ENOMEM; 607178825Sdfr } 608178825Sdfr *digest->request.method = strdup(method); 609178825Sdfr if (*digest->request.method == NULL) { 610233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 611178825Sdfr free(digest->request.method); 612178825Sdfr digest->request.method = NULL; 613178825Sdfr return ENOMEM; 614178825Sdfr } 615178825Sdfr return 0; 616178825Sdfr} 617178825Sdfr 618233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 619178825Sdfrkrb5_digest_set_uri(krb5_context context, 620178825Sdfr krb5_digest digest, 621178825Sdfr const char *uri) 622178825Sdfr{ 623178825Sdfr if (digest->request.uri) { 624233294Sstas krb5_set_error_message(context, EINVAL, N_("uri already set", "")); 625178825Sdfr return EINVAL; 626178825Sdfr } 627178825Sdfr digest->request.uri = malloc(sizeof(*digest->request.uri)); 628178825Sdfr if (digest->request.uri == NULL) { 629233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 630178825Sdfr return ENOMEM; 631178825Sdfr } 632178825Sdfr *digest->request.uri = strdup(uri); 633178825Sdfr if (*digest->request.uri == NULL) { 634233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 635178825Sdfr free(digest->request.uri); 636178825Sdfr digest->request.uri = NULL; 637178825Sdfr return ENOMEM; 638178825Sdfr } 639178825Sdfr return 0; 640178825Sdfr} 641178825Sdfr 642233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 643178825Sdfrkrb5_digest_set_nonceCount(krb5_context context, 644178825Sdfr krb5_digest digest, 645178825Sdfr const char *nonce_count) 646178825Sdfr{ 647178825Sdfr if (digest->request.nonceCount) { 648233294Sstas krb5_set_error_message(context, EINVAL, 649233294Sstas N_("nonceCount already set", "")); 650178825Sdfr return EINVAL; 651178825Sdfr } 652233294Sstas digest->request.nonceCount = 653178825Sdfr malloc(sizeof(*digest->request.nonceCount)); 654178825Sdfr if (digest->request.nonceCount == NULL) { 655233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 656178825Sdfr return ENOMEM; 657178825Sdfr } 658178825Sdfr *digest->request.nonceCount = strdup(nonce_count); 659178825Sdfr if (*digest->request.nonceCount == NULL) { 660233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 661178825Sdfr free(digest->request.nonceCount); 662178825Sdfr digest->request.nonceCount = NULL; 663178825Sdfr return ENOMEM; 664178825Sdfr } 665178825Sdfr return 0; 666178825Sdfr} 667178825Sdfr 668233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 669178825Sdfrkrb5_digest_set_qop(krb5_context context, 670178825Sdfr krb5_digest digest, 671178825Sdfr const char *qop) 672178825Sdfr{ 673178825Sdfr if (digest->request.qop) { 674233294Sstas krb5_set_error_message(context, EINVAL, "qop already set"); 675178825Sdfr return EINVAL; 676178825Sdfr } 677178825Sdfr digest->request.qop = malloc(sizeof(*digest->request.qop)); 678178825Sdfr if (digest->request.qop == NULL) { 679233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 680178825Sdfr return ENOMEM; 681178825Sdfr } 682178825Sdfr *digest->request.qop = strdup(qop); 683178825Sdfr if (*digest->request.qop == NULL) { 684233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 685178825Sdfr free(digest->request.qop); 686178825Sdfr digest->request.qop = NULL; 687178825Sdfr return ENOMEM; 688178825Sdfr } 689178825Sdfr return 0; 690178825Sdfr} 691178825Sdfr 692233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 693178825Sdfrkrb5_digest_set_responseData(krb5_context context, 694178825Sdfr krb5_digest digest, 695178825Sdfr const char *response) 696178825Sdfr{ 697178825Sdfr digest->request.responseData = strdup(response); 698178825Sdfr if (digest->request.responseData == NULL) { 699233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 700178825Sdfr return ENOMEM; 701178825Sdfr } 702178825Sdfr return 0; 703178825Sdfr} 704178825Sdfr 705233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 706178825Sdfrkrb5_digest_request(krb5_context context, 707178825Sdfr krb5_digest digest, 708178825Sdfr krb5_realm realm, 709178825Sdfr krb5_ccache ccache) 710178825Sdfr{ 711178825Sdfr DigestReqInner ireq; 712178825Sdfr DigestRepInner irep; 713178825Sdfr krb5_error_code ret; 714178825Sdfr 715178825Sdfr memset(&ireq, 0, sizeof(ireq)); 716178825Sdfr memset(&irep, 0, sizeof(irep)); 717178825Sdfr 718178825Sdfr ireq.element = choice_DigestReqInner_digestRequest; 719178825Sdfr ireq.u.digestRequest = digest->request; 720178825Sdfr 721178825Sdfr if (digest->request.type == NULL) { 722178825Sdfr if (digest->init.type == NULL) { 723233294Sstas krb5_set_error_message(context, EINVAL, 724233294Sstas N_("Type missing from req", "")); 725178825Sdfr return EINVAL; 726178825Sdfr } 727178825Sdfr ireq.u.digestRequest.type = digest->init.type; 728178825Sdfr } 729178825Sdfr 730233294Sstas if (ireq.u.digestRequest.digest == NULL) { 731233294Sstas static char md5[] = "md5"; 732233294Sstas ireq.u.digestRequest.digest = md5; 733233294Sstas } 734178825Sdfr 735178825Sdfr ret = digest_request(context, realm, ccache, 736178825Sdfr KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 737178825Sdfr if (ret) 738178825Sdfr return ret; 739178825Sdfr 740178825Sdfr if (irep.element == choice_DigestRepInner_error) { 741178825Sdfr ret = irep.u.error.code; 742233294Sstas krb5_set_error_message(context, ret, 743233294Sstas N_("Digest response error: %s", ""), 744233294Sstas irep.u.error.reason); 745178825Sdfr goto out; 746178825Sdfr } 747178825Sdfr 748178825Sdfr if (irep.element != choice_DigestRepInner_response) { 749233294Sstas krb5_set_error_message(context, EINVAL, 750233294Sstas N_("digest reply not an DigestResponse", "")); 751178825Sdfr ret = EINVAL; 752178825Sdfr goto out; 753178825Sdfr } 754178825Sdfr 755178825Sdfr ret = copy_DigestResponse(&irep.u.response, &digest->response); 756178825Sdfr if (ret) { 757233294Sstas krb5_set_error_message(context, ret, 758233294Sstas N_("Failed to copy initReply,", "")); 759178825Sdfr goto out; 760178825Sdfr } 761178825Sdfr 762233294Sstas out: 763178825Sdfr free_DigestRepInner(&irep); 764178825Sdfr 765178825Sdfr return ret; 766178825Sdfr} 767178825Sdfr 768233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 769233294Sstaskrb5_digest_rep_get_status(krb5_context context, 770178825Sdfr krb5_digest digest) 771178825Sdfr{ 772178825Sdfr return digest->response.success ? TRUE : FALSE; 773178825Sdfr} 774178825Sdfr 775233294SstasKRB5_LIB_FUNCTION const char * KRB5_LIB_CALL 776178825Sdfrkrb5_digest_get_rsp(krb5_context context, 777178825Sdfr krb5_digest digest) 778178825Sdfr{ 779178825Sdfr if (digest->response.rsp == NULL) 780178825Sdfr return NULL; 781178825Sdfr return *digest->response.rsp; 782178825Sdfr} 783178825Sdfr 784233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 785178825Sdfrkrb5_digest_get_tickets(krb5_context context, 786178825Sdfr krb5_digest digest, 787178825Sdfr Ticket **tickets) 788178825Sdfr{ 789178825Sdfr *tickets = NULL; 790178825Sdfr return 0; 791178825Sdfr} 792178825Sdfr 793178825Sdfr 794233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 795178825Sdfrkrb5_digest_get_client_binding(krb5_context context, 796178825Sdfr krb5_digest digest, 797178825Sdfr char **type, 798178825Sdfr char **binding) 799178825Sdfr{ 800178825Sdfr if (digest->response.channel) { 801178825Sdfr *type = strdup(digest->response.channel->cb_type); 802178825Sdfr *binding = strdup(digest->response.channel->cb_binding); 803178825Sdfr if (*type == NULL || *binding == NULL) { 804178825Sdfr free(*type); 805178825Sdfr free(*binding); 806233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 807178825Sdfr return ENOMEM; 808178825Sdfr } 809178825Sdfr } else { 810178825Sdfr *type = NULL; 811178825Sdfr *binding = NULL; 812178825Sdfr } 813178825Sdfr return 0; 814178825Sdfr} 815178825Sdfr 816233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 817178825Sdfrkrb5_digest_get_session_key(krb5_context context, 818178825Sdfr krb5_digest digest, 819178825Sdfr krb5_data *data) 820178825Sdfr{ 821178825Sdfr krb5_error_code ret; 822178825Sdfr 823178825Sdfr krb5_data_zero(data); 824178825Sdfr if (digest->response.session_key == NULL) 825178825Sdfr return 0; 826178825Sdfr ret = der_copy_octet_string(digest->response.session_key, data); 827178825Sdfr if (ret) 828233294Sstas krb5_clear_error_message(context); 829178825Sdfr 830178825Sdfr return ret; 831178825Sdfr} 832178825Sdfr 833178825Sdfrstruct krb5_ntlm_data { 834178825Sdfr NTLMInit init; 835178825Sdfr NTLMInitReply initReply; 836178825Sdfr NTLMRequest request; 837178825Sdfr NTLMResponse response; 838178825Sdfr}; 839178825Sdfr 840233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 841233294Sstaskrb5_ntlm_alloc(krb5_context context, 842178825Sdfr krb5_ntlm *ntlm) 843178825Sdfr{ 844178825Sdfr *ntlm = calloc(1, sizeof(**ntlm)); 845178825Sdfr if (*ntlm == NULL) { 846233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 847178825Sdfr return ENOMEM; 848178825Sdfr } 849178825Sdfr return 0; 850178825Sdfr} 851178825Sdfr 852233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 853178825Sdfrkrb5_ntlm_free(krb5_context context, krb5_ntlm ntlm) 854178825Sdfr{ 855178825Sdfr free_NTLMInit(&ntlm->init); 856178825Sdfr free_NTLMInitReply(&ntlm->initReply); 857178825Sdfr free_NTLMRequest(&ntlm->request); 858178825Sdfr free_NTLMResponse(&ntlm->response); 859178825Sdfr memset(ntlm, 0, sizeof(*ntlm)); 860178825Sdfr free(ntlm); 861178825Sdfr return 0; 862178825Sdfr} 863178825Sdfr 864178825Sdfr 865233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 866233294Sstaskrb5_ntlm_init_request(krb5_context context, 867178825Sdfr krb5_ntlm ntlm, 868178825Sdfr krb5_realm realm, 869178825Sdfr krb5_ccache ccache, 870178825Sdfr uint32_t flags, 871178825Sdfr const char *hostname, 872178825Sdfr const char *domainname) 873178825Sdfr{ 874178825Sdfr DigestReqInner ireq; 875178825Sdfr DigestRepInner irep; 876178825Sdfr krb5_error_code ret; 877178825Sdfr 878178825Sdfr memset(&ireq, 0, sizeof(ireq)); 879178825Sdfr memset(&irep, 0, sizeof(irep)); 880178825Sdfr 881178825Sdfr ntlm->init.flags = flags; 882178825Sdfr if (hostname) { 883178825Sdfr ALLOC(ntlm->init.hostname, 1); 884178825Sdfr *ntlm->init.hostname = strdup(hostname); 885178825Sdfr } 886178825Sdfr if (domainname) { 887178825Sdfr ALLOC(ntlm->init.domain, 1); 888178825Sdfr *ntlm->init.domain = strdup(domainname); 889178825Sdfr } 890178825Sdfr 891178825Sdfr ireq.element = choice_DigestReqInner_ntlmInit; 892178825Sdfr ireq.u.ntlmInit = ntlm->init; 893178825Sdfr 894178825Sdfr ret = digest_request(context, realm, ccache, 895178825Sdfr KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 896178825Sdfr if (ret) 897178825Sdfr goto out; 898178825Sdfr 899178825Sdfr if (irep.element == choice_DigestRepInner_error) { 900178825Sdfr ret = irep.u.error.code; 901233294Sstas krb5_set_error_message(context, ret, N_("Digest init error: %s", ""), 902233294Sstas irep.u.error.reason); 903178825Sdfr goto out; 904178825Sdfr } 905178825Sdfr 906178825Sdfr if (irep.element != choice_DigestRepInner_ntlmInitReply) { 907178825Sdfr ret = EINVAL; 908233294Sstas krb5_set_error_message(context, ret, 909233294Sstas N_("ntlm reply not an initReply", "")); 910178825Sdfr goto out; 911178825Sdfr } 912178825Sdfr 913178825Sdfr ret = copy_NTLMInitReply(&irep.u.ntlmInitReply, &ntlm->initReply); 914178825Sdfr if (ret) { 915233294Sstas krb5_set_error_message(context, ret, 916233294Sstas N_("Failed to copy initReply", "")); 917178825Sdfr goto out; 918178825Sdfr } 919178825Sdfr 920233294Sstas out: 921178825Sdfr free_DigestRepInner(&irep); 922178825Sdfr 923178825Sdfr return ret; 924178825Sdfr} 925178825Sdfr 926233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 927178825Sdfrkrb5_ntlm_init_get_flags(krb5_context context, 928178825Sdfr krb5_ntlm ntlm, 929178825Sdfr uint32_t *flags) 930178825Sdfr{ 931178825Sdfr *flags = ntlm->initReply.flags; 932178825Sdfr return 0; 933178825Sdfr} 934178825Sdfr 935233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 936178825Sdfrkrb5_ntlm_init_get_challange(krb5_context context, 937178825Sdfr krb5_ntlm ntlm, 938178825Sdfr krb5_data *challange) 939178825Sdfr{ 940178825Sdfr krb5_error_code ret; 941178825Sdfr 942178825Sdfr ret = der_copy_octet_string(&ntlm->initReply.challange, challange); 943178825Sdfr if (ret) 944233294Sstas krb5_clear_error_message(context); 945178825Sdfr 946178825Sdfr return ret; 947178825Sdfr} 948178825Sdfr 949233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 950178825Sdfrkrb5_ntlm_init_get_opaque(krb5_context context, 951178825Sdfr krb5_ntlm ntlm, 952178825Sdfr krb5_data *opaque) 953178825Sdfr{ 954178825Sdfr krb5_error_code ret; 955178825Sdfr 956178825Sdfr ret = der_copy_octet_string(&ntlm->initReply.opaque, opaque); 957178825Sdfr if (ret) 958233294Sstas krb5_clear_error_message(context); 959178825Sdfr 960178825Sdfr return ret; 961178825Sdfr} 962178825Sdfr 963233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 964178825Sdfrkrb5_ntlm_init_get_targetname(krb5_context context, 965178825Sdfr krb5_ntlm ntlm, 966178825Sdfr char **name) 967178825Sdfr{ 968178825Sdfr *name = strdup(ntlm->initReply.targetname); 969178825Sdfr if (*name == NULL) { 970233294Sstas krb5_clear_error_message(context); 971178825Sdfr return ENOMEM; 972178825Sdfr } 973178825Sdfr return 0; 974178825Sdfr} 975178825Sdfr 976233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 977178825Sdfrkrb5_ntlm_init_get_targetinfo(krb5_context context, 978178825Sdfr krb5_ntlm ntlm, 979178825Sdfr krb5_data *data) 980178825Sdfr{ 981178825Sdfr krb5_error_code ret; 982178825Sdfr 983178825Sdfr if (ntlm->initReply.targetinfo == NULL) { 984178825Sdfr krb5_data_zero(data); 985178825Sdfr return 0; 986178825Sdfr } 987178825Sdfr 988178825Sdfr ret = krb5_data_copy(data, 989178825Sdfr ntlm->initReply.targetinfo->data, 990178825Sdfr ntlm->initReply.targetinfo->length); 991178825Sdfr if (ret) { 992233294Sstas krb5_clear_error_message(context); 993178825Sdfr return ret; 994178825Sdfr } 995178825Sdfr return 0; 996178825Sdfr} 997178825Sdfr 998178825Sdfr 999233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1000178825Sdfrkrb5_ntlm_request(krb5_context context, 1001178825Sdfr krb5_ntlm ntlm, 1002178825Sdfr krb5_realm realm, 1003178825Sdfr krb5_ccache ccache) 1004178825Sdfr{ 1005178825Sdfr DigestReqInner ireq; 1006178825Sdfr DigestRepInner irep; 1007178825Sdfr krb5_error_code ret; 1008178825Sdfr 1009178825Sdfr memset(&ireq, 0, sizeof(ireq)); 1010178825Sdfr memset(&irep, 0, sizeof(irep)); 1011178825Sdfr 1012178825Sdfr ireq.element = choice_DigestReqInner_ntlmRequest; 1013178825Sdfr ireq.u.ntlmRequest = ntlm->request; 1014178825Sdfr 1015178825Sdfr ret = digest_request(context, realm, ccache, 1016178825Sdfr KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 1017178825Sdfr if (ret) 1018178825Sdfr return ret; 1019178825Sdfr 1020178825Sdfr if (irep.element == choice_DigestRepInner_error) { 1021178825Sdfr ret = irep.u.error.code; 1022233294Sstas krb5_set_error_message(context, ret, 1023233294Sstas N_("NTLM response error: %s", ""), 1024233294Sstas irep.u.error.reason); 1025178825Sdfr goto out; 1026178825Sdfr } 1027178825Sdfr 1028178825Sdfr if (irep.element != choice_DigestRepInner_ntlmResponse) { 1029178825Sdfr ret = EINVAL; 1030233294Sstas krb5_set_error_message(context, ret, 1031233294Sstas N_("NTLM reply not an NTLMResponse", "")); 1032178825Sdfr goto out; 1033178825Sdfr } 1034178825Sdfr 1035178825Sdfr ret = copy_NTLMResponse(&irep.u.ntlmResponse, &ntlm->response); 1036178825Sdfr if (ret) { 1037233294Sstas krb5_set_error_message(context, ret, 1038233294Sstas N_("Failed to copy NTLMResponse", "")); 1039178825Sdfr goto out; 1040178825Sdfr } 1041178825Sdfr 1042233294Sstas out: 1043178825Sdfr free_DigestRepInner(&irep); 1044178825Sdfr 1045178825Sdfr return ret; 1046178825Sdfr} 1047178825Sdfr 1048233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1049233294Sstaskrb5_ntlm_req_set_flags(krb5_context context, 1050178825Sdfr krb5_ntlm ntlm, 1051178825Sdfr uint32_t flags) 1052178825Sdfr{ 1053178825Sdfr ntlm->request.flags = flags; 1054178825Sdfr return 0; 1055178825Sdfr} 1056178825Sdfr 1057233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1058233294Sstaskrb5_ntlm_req_set_username(krb5_context context, 1059178825Sdfr krb5_ntlm ntlm, 1060178825Sdfr const char *username) 1061178825Sdfr{ 1062178825Sdfr ntlm->request.username = strdup(username); 1063178825Sdfr if (ntlm->request.username == NULL) { 1064233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1065178825Sdfr return ENOMEM; 1066178825Sdfr } 1067178825Sdfr return 0; 1068178825Sdfr} 1069178825Sdfr 1070233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1071233294Sstaskrb5_ntlm_req_set_targetname(krb5_context context, 1072178825Sdfr krb5_ntlm ntlm, 1073178825Sdfr const char *targetname) 1074178825Sdfr{ 1075178825Sdfr ntlm->request.targetname = strdup(targetname); 1076178825Sdfr if (ntlm->request.targetname == NULL) { 1077233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1078178825Sdfr return ENOMEM; 1079178825Sdfr } 1080178825Sdfr return 0; 1081178825Sdfr} 1082178825Sdfr 1083233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1084233294Sstaskrb5_ntlm_req_set_lm(krb5_context context, 1085178825Sdfr krb5_ntlm ntlm, 1086178825Sdfr void *hash, size_t len) 1087178825Sdfr{ 1088178825Sdfr ntlm->request.lm.data = malloc(len); 1089233294Sstas if (ntlm->request.lm.data == NULL && len != 0) { 1090233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1091178825Sdfr return ENOMEM; 1092178825Sdfr } 1093178825Sdfr ntlm->request.lm.length = len; 1094178825Sdfr memcpy(ntlm->request.lm.data, hash, len); 1095178825Sdfr return 0; 1096178825Sdfr} 1097178825Sdfr 1098233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1099233294Sstaskrb5_ntlm_req_set_ntlm(krb5_context context, 1100178825Sdfr krb5_ntlm ntlm, 1101178825Sdfr void *hash, size_t len) 1102178825Sdfr{ 1103178825Sdfr ntlm->request.ntlm.data = malloc(len); 1104233294Sstas if (ntlm->request.ntlm.data == NULL && len != 0) { 1105233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1106178825Sdfr return ENOMEM; 1107178825Sdfr } 1108178825Sdfr ntlm->request.ntlm.length = len; 1109178825Sdfr memcpy(ntlm->request.ntlm.data, hash, len); 1110178825Sdfr return 0; 1111178825Sdfr} 1112178825Sdfr 1113233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1114233294Sstaskrb5_ntlm_req_set_opaque(krb5_context context, 1115178825Sdfr krb5_ntlm ntlm, 1116178825Sdfr krb5_data *opaque) 1117178825Sdfr{ 1118178825Sdfr ntlm->request.opaque.data = malloc(opaque->length); 1119233294Sstas if (ntlm->request.opaque.data == NULL && opaque->length != 0) { 1120233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1121178825Sdfr return ENOMEM; 1122178825Sdfr } 1123178825Sdfr ntlm->request.opaque.length = opaque->length; 1124178825Sdfr memcpy(ntlm->request.opaque.data, opaque->data, opaque->length); 1125178825Sdfr return 0; 1126178825Sdfr} 1127178825Sdfr 1128233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1129233294Sstaskrb5_ntlm_req_set_session(krb5_context context, 1130178825Sdfr krb5_ntlm ntlm, 1131178825Sdfr void *sessionkey, size_t length) 1132178825Sdfr{ 1133178825Sdfr ntlm->request.sessionkey = calloc(1, sizeof(*ntlm->request.sessionkey)); 1134178825Sdfr if (ntlm->request.sessionkey == NULL) { 1135233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1136178825Sdfr return ENOMEM; 1137178825Sdfr } 1138178825Sdfr ntlm->request.sessionkey->data = malloc(length); 1139233294Sstas if (ntlm->request.sessionkey->data == NULL && length != 0) { 1140233294Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1141178825Sdfr return ENOMEM; 1142178825Sdfr } 1143178825Sdfr memcpy(ntlm->request.sessionkey->data, sessionkey, length); 1144178825Sdfr ntlm->request.sessionkey->length = length; 1145178825Sdfr return 0; 1146178825Sdfr} 1147178825Sdfr 1148233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1149233294Sstaskrb5_ntlm_rep_get_status(krb5_context context, 1150178825Sdfr krb5_ntlm ntlm) 1151178825Sdfr{ 1152178825Sdfr return ntlm->response.success ? TRUE : FALSE; 1153178825Sdfr} 1154178825Sdfr 1155233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1156233294Sstaskrb5_ntlm_rep_get_sessionkey(krb5_context context, 1157178825Sdfr krb5_ntlm ntlm, 1158178825Sdfr krb5_data *data) 1159178825Sdfr{ 1160178825Sdfr if (ntlm->response.sessionkey == NULL) { 1161233294Sstas krb5_set_error_message(context, EINVAL, 1162233294Sstas N_("no ntlm session key", "")); 1163178825Sdfr return EINVAL; 1164178825Sdfr } 1165233294Sstas krb5_clear_error_message(context); 1166178825Sdfr return krb5_data_copy(data, 1167178825Sdfr ntlm->response.sessionkey->data, 1168178825Sdfr ntlm->response.sessionkey->length); 1169178825Sdfr} 1170178825Sdfr 1171178825Sdfr/** 1172178825Sdfr * Get the supported/allowed mechanism for this principal. 1173178825Sdfr * 1174178825Sdfr * @param context A Keberos context. 1175178825Sdfr * @param realm The realm of the KDC. 1176178825Sdfr * @param ccache The credential cache to use when talking to the KDC. 1177178825Sdfr * @param flags The supported mechanism. 1178178825Sdfr * 1179178825Sdfr * @return Return an error code or 0. 1180178825Sdfr * 1181178825Sdfr * @ingroup krb5_digest 1182178825Sdfr */ 1183178825Sdfr 1184233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1185178825Sdfrkrb5_digest_probe(krb5_context context, 1186178825Sdfr krb5_realm realm, 1187178825Sdfr krb5_ccache ccache, 1188178825Sdfr unsigned *flags) 1189178825Sdfr{ 1190178825Sdfr DigestReqInner ireq; 1191178825Sdfr DigestRepInner irep; 1192178825Sdfr krb5_error_code ret; 1193178825Sdfr 1194178825Sdfr memset(&ireq, 0, sizeof(ireq)); 1195178825Sdfr memset(&irep, 0, sizeof(irep)); 1196178825Sdfr 1197178825Sdfr ireq.element = choice_DigestReqInner_supportedMechs; 1198178825Sdfr 1199178825Sdfr ret = digest_request(context, realm, ccache, 1200178825Sdfr KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 1201178825Sdfr if (ret) 1202178825Sdfr goto out; 1203178825Sdfr 1204178825Sdfr if (irep.element == choice_DigestRepInner_error) { 1205178825Sdfr ret = irep.u.error.code; 1206233294Sstas krb5_set_error_message(context, ret, "Digest probe error: %s", 1207233294Sstas irep.u.error.reason); 1208178825Sdfr goto out; 1209178825Sdfr } 1210178825Sdfr 1211178825Sdfr if (irep.element != choice_DigestRepInner_supportedMechs) { 1212178825Sdfr ret = EINVAL; 1213233294Sstas krb5_set_error_message(context, ret, "Digest reply not an probe"); 1214178825Sdfr goto out; 1215178825Sdfr } 1216178825Sdfr 1217178825Sdfr *flags = DigestTypes2int(irep.u.supportedMechs); 1218178825Sdfr 1219233294Sstas out: 1220178825Sdfr free_DigestRepInner(&irep); 1221178825Sdfr 1222178825Sdfr return ret; 1223178825Sdfr} 1224233294Sstas 1225233294Sstas#endif /* HEIMDAL_SMALLER */ 1226