1*c19800e8SDoug Rabson /* 2*c19800e8SDoug Rabson * Copyright (c) 2006 Kungliga Tekniska H�gskolan 3*c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 4*c19800e8SDoug Rabson * All rights reserved. 5*c19800e8SDoug Rabson * 6*c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 7*c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 8*c19800e8SDoug Rabson * are met: 9*c19800e8SDoug Rabson * 10*c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 11*c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 12*c19800e8SDoug Rabson * 13*c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 14*c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 15*c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 16*c19800e8SDoug Rabson * 17*c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 18*c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 19*c19800e8SDoug Rabson * without specific prior written permission. 20*c19800e8SDoug Rabson * 21*c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22*c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25*c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*c19800e8SDoug Rabson * SUCH DAMAGE. 32*c19800e8SDoug Rabson */ 33*c19800e8SDoug Rabson 34*c19800e8SDoug Rabson #include "krb5_locl.h" 35*c19800e8SDoug Rabson RCSID("$Id: digest.c 22156 2007-12-04 20:02:49Z lha $"); 36*c19800e8SDoug Rabson #include "digest_asn1.h" 37*c19800e8SDoug Rabson 38*c19800e8SDoug Rabson struct krb5_digest_data { 39*c19800e8SDoug Rabson char *cbtype; 40*c19800e8SDoug Rabson char *cbbinding; 41*c19800e8SDoug Rabson 42*c19800e8SDoug Rabson DigestInit init; 43*c19800e8SDoug Rabson DigestInitReply initReply; 44*c19800e8SDoug Rabson DigestRequest request; 45*c19800e8SDoug Rabson DigestResponse response; 46*c19800e8SDoug Rabson }; 47*c19800e8SDoug Rabson 48*c19800e8SDoug Rabson krb5_error_code 49*c19800e8SDoug Rabson krb5_digest_alloc(krb5_context context, krb5_digest *digest) 50*c19800e8SDoug Rabson { 51*c19800e8SDoug Rabson krb5_digest d; 52*c19800e8SDoug Rabson 53*c19800e8SDoug Rabson d = calloc(1, sizeof(*d)); 54*c19800e8SDoug Rabson if (d == NULL) { 55*c19800e8SDoug Rabson *digest = NULL; 56*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 57*c19800e8SDoug Rabson return ENOMEM; 58*c19800e8SDoug Rabson } 59*c19800e8SDoug Rabson *digest = d; 60*c19800e8SDoug Rabson 61*c19800e8SDoug Rabson return 0; 62*c19800e8SDoug Rabson } 63*c19800e8SDoug Rabson 64*c19800e8SDoug Rabson void 65*c19800e8SDoug Rabson krb5_digest_free(krb5_digest digest) 66*c19800e8SDoug Rabson { 67*c19800e8SDoug Rabson if (digest == NULL) 68*c19800e8SDoug Rabson return; 69*c19800e8SDoug Rabson free_DigestInit(&digest->init); 70*c19800e8SDoug Rabson free_DigestInitReply(&digest->initReply); 71*c19800e8SDoug Rabson free_DigestRequest(&digest->request); 72*c19800e8SDoug Rabson free_DigestResponse(&digest->response); 73*c19800e8SDoug Rabson memset(digest, 0, sizeof(*digest)); 74*c19800e8SDoug Rabson free(digest); 75*c19800e8SDoug Rabson return; 76*c19800e8SDoug Rabson } 77*c19800e8SDoug Rabson 78*c19800e8SDoug Rabson krb5_error_code 79*c19800e8SDoug Rabson krb5_digest_set_server_cb(krb5_context context, 80*c19800e8SDoug Rabson krb5_digest digest, 81*c19800e8SDoug Rabson const char *type, 82*c19800e8SDoug Rabson const char *binding) 83*c19800e8SDoug Rabson { 84*c19800e8SDoug Rabson if (digest->init.channel) { 85*c19800e8SDoug Rabson krb5_set_error_string(context, "server channel binding already set"); 86*c19800e8SDoug Rabson return EINVAL; 87*c19800e8SDoug Rabson } 88*c19800e8SDoug Rabson digest->init.channel = calloc(1, sizeof(*digest->init.channel)); 89*c19800e8SDoug Rabson if (digest->init.channel == NULL) 90*c19800e8SDoug Rabson goto error; 91*c19800e8SDoug Rabson 92*c19800e8SDoug Rabson digest->init.channel->cb_type = strdup(type); 93*c19800e8SDoug Rabson if (digest->init.channel->cb_type == NULL) 94*c19800e8SDoug Rabson goto error; 95*c19800e8SDoug Rabson 96*c19800e8SDoug Rabson digest->init.channel->cb_binding = strdup(binding); 97*c19800e8SDoug Rabson if (digest->init.channel->cb_binding == NULL) 98*c19800e8SDoug Rabson goto error; 99*c19800e8SDoug Rabson return 0; 100*c19800e8SDoug Rabson error: 101*c19800e8SDoug Rabson if (digest->init.channel) { 102*c19800e8SDoug Rabson free(digest->init.channel->cb_type); 103*c19800e8SDoug Rabson free(digest->init.channel->cb_binding); 104*c19800e8SDoug Rabson free(digest->init.channel); 105*c19800e8SDoug Rabson digest->init.channel = NULL; 106*c19800e8SDoug Rabson } 107*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 108*c19800e8SDoug Rabson return ENOMEM; 109*c19800e8SDoug Rabson } 110*c19800e8SDoug Rabson 111*c19800e8SDoug Rabson krb5_error_code 112*c19800e8SDoug Rabson krb5_digest_set_type(krb5_context context, 113*c19800e8SDoug Rabson krb5_digest digest, 114*c19800e8SDoug Rabson const char *type) 115*c19800e8SDoug Rabson { 116*c19800e8SDoug Rabson if (digest->init.type) { 117*c19800e8SDoug Rabson krb5_set_error_string(context, "client type already set"); 118*c19800e8SDoug Rabson return EINVAL; 119*c19800e8SDoug Rabson } 120*c19800e8SDoug Rabson digest->init.type = strdup(type); 121*c19800e8SDoug Rabson if (digest->init.type == NULL) { 122*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 123*c19800e8SDoug Rabson return ENOMEM; 124*c19800e8SDoug Rabson } 125*c19800e8SDoug Rabson return 0; 126*c19800e8SDoug Rabson } 127*c19800e8SDoug Rabson 128*c19800e8SDoug Rabson krb5_error_code 129*c19800e8SDoug Rabson krb5_digest_set_hostname(krb5_context context, 130*c19800e8SDoug Rabson krb5_digest digest, 131*c19800e8SDoug Rabson const char *hostname) 132*c19800e8SDoug Rabson { 133*c19800e8SDoug Rabson if (digest->init.hostname) { 134*c19800e8SDoug Rabson krb5_set_error_string(context, "server hostname already set"); 135*c19800e8SDoug Rabson return EINVAL; 136*c19800e8SDoug Rabson } 137*c19800e8SDoug Rabson digest->init.hostname = malloc(sizeof(*digest->init.hostname)); 138*c19800e8SDoug Rabson if (digest->init.hostname == NULL) { 139*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 140*c19800e8SDoug Rabson return ENOMEM; 141*c19800e8SDoug Rabson } 142*c19800e8SDoug Rabson *digest->init.hostname = strdup(hostname); 143*c19800e8SDoug Rabson if (*digest->init.hostname == NULL) { 144*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 145*c19800e8SDoug Rabson free(digest->init.hostname); 146*c19800e8SDoug Rabson digest->init.hostname = NULL; 147*c19800e8SDoug Rabson return ENOMEM; 148*c19800e8SDoug Rabson } 149*c19800e8SDoug Rabson return 0; 150*c19800e8SDoug Rabson } 151*c19800e8SDoug Rabson 152*c19800e8SDoug Rabson const char * 153*c19800e8SDoug Rabson krb5_digest_get_server_nonce(krb5_context context, 154*c19800e8SDoug Rabson krb5_digest digest) 155*c19800e8SDoug Rabson { 156*c19800e8SDoug Rabson return digest->initReply.nonce; 157*c19800e8SDoug Rabson } 158*c19800e8SDoug Rabson 159*c19800e8SDoug Rabson krb5_error_code 160*c19800e8SDoug Rabson krb5_digest_set_server_nonce(krb5_context context, 161*c19800e8SDoug Rabson krb5_digest digest, 162*c19800e8SDoug Rabson const char *nonce) 163*c19800e8SDoug Rabson { 164*c19800e8SDoug Rabson if (digest->request.serverNonce) { 165*c19800e8SDoug Rabson krb5_set_error_string(context, "nonce already set"); 166*c19800e8SDoug Rabson return EINVAL; 167*c19800e8SDoug Rabson } 168*c19800e8SDoug Rabson digest->request.serverNonce = strdup(nonce); 169*c19800e8SDoug Rabson if (digest->request.serverNonce == NULL) { 170*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 171*c19800e8SDoug Rabson return ENOMEM; 172*c19800e8SDoug Rabson } 173*c19800e8SDoug Rabson return 0; 174*c19800e8SDoug Rabson } 175*c19800e8SDoug Rabson 176*c19800e8SDoug Rabson const char * 177*c19800e8SDoug Rabson krb5_digest_get_opaque(krb5_context context, 178*c19800e8SDoug Rabson krb5_digest digest) 179*c19800e8SDoug Rabson { 180*c19800e8SDoug Rabson return digest->initReply.opaque; 181*c19800e8SDoug Rabson } 182*c19800e8SDoug Rabson 183*c19800e8SDoug Rabson krb5_error_code 184*c19800e8SDoug Rabson krb5_digest_set_opaque(krb5_context context, 185*c19800e8SDoug Rabson krb5_digest digest, 186*c19800e8SDoug Rabson const char *opaque) 187*c19800e8SDoug Rabson { 188*c19800e8SDoug Rabson if (digest->request.opaque) { 189*c19800e8SDoug Rabson krb5_set_error_string(context, "opaque already set"); 190*c19800e8SDoug Rabson return EINVAL; 191*c19800e8SDoug Rabson } 192*c19800e8SDoug Rabson digest->request.opaque = strdup(opaque); 193*c19800e8SDoug Rabson if (digest->request.opaque == NULL) { 194*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 195*c19800e8SDoug Rabson return ENOMEM; 196*c19800e8SDoug Rabson } 197*c19800e8SDoug Rabson return 0; 198*c19800e8SDoug Rabson } 199*c19800e8SDoug Rabson 200*c19800e8SDoug Rabson const char * 201*c19800e8SDoug Rabson krb5_digest_get_identifier(krb5_context context, 202*c19800e8SDoug Rabson krb5_digest digest) 203*c19800e8SDoug Rabson { 204*c19800e8SDoug Rabson if (digest->initReply.identifier == NULL) 205*c19800e8SDoug Rabson return NULL; 206*c19800e8SDoug Rabson return *digest->initReply.identifier; 207*c19800e8SDoug Rabson } 208*c19800e8SDoug Rabson 209*c19800e8SDoug Rabson krb5_error_code 210*c19800e8SDoug Rabson krb5_digest_set_identifier(krb5_context context, 211*c19800e8SDoug Rabson krb5_digest digest, 212*c19800e8SDoug Rabson const char *id) 213*c19800e8SDoug Rabson { 214*c19800e8SDoug Rabson if (digest->request.identifier) { 215*c19800e8SDoug Rabson krb5_set_error_string(context, "identifier already set"); 216*c19800e8SDoug Rabson return EINVAL; 217*c19800e8SDoug Rabson } 218*c19800e8SDoug Rabson digest->request.identifier = calloc(1, sizeof(*digest->request.identifier)); 219*c19800e8SDoug Rabson if (digest->request.identifier == NULL) { 220*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 221*c19800e8SDoug Rabson return ENOMEM; 222*c19800e8SDoug Rabson } 223*c19800e8SDoug Rabson *digest->request.identifier = strdup(id); 224*c19800e8SDoug Rabson if (*digest->request.identifier == NULL) { 225*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 226*c19800e8SDoug Rabson free(digest->request.identifier); 227*c19800e8SDoug Rabson digest->request.identifier = NULL; 228*c19800e8SDoug Rabson return ENOMEM; 229*c19800e8SDoug Rabson } 230*c19800e8SDoug Rabson return 0; 231*c19800e8SDoug Rabson } 232*c19800e8SDoug Rabson 233*c19800e8SDoug Rabson static krb5_error_code 234*c19800e8SDoug Rabson digest_request(krb5_context context, 235*c19800e8SDoug Rabson krb5_realm realm, 236*c19800e8SDoug Rabson krb5_ccache ccache, 237*c19800e8SDoug Rabson krb5_key_usage usage, 238*c19800e8SDoug Rabson const DigestReqInner *ireq, 239*c19800e8SDoug Rabson DigestRepInner *irep) 240*c19800e8SDoug Rabson { 241*c19800e8SDoug Rabson DigestREQ req; 242*c19800e8SDoug Rabson DigestREP rep; 243*c19800e8SDoug Rabson krb5_error_code ret; 244*c19800e8SDoug Rabson krb5_data data, data2; 245*c19800e8SDoug Rabson size_t size; 246*c19800e8SDoug Rabson krb5_crypto crypto = NULL; 247*c19800e8SDoug Rabson krb5_auth_context ac = NULL; 248*c19800e8SDoug Rabson krb5_principal principal = NULL; 249*c19800e8SDoug Rabson krb5_ccache id = NULL; 250*c19800e8SDoug Rabson krb5_realm r = NULL; 251*c19800e8SDoug Rabson 252*c19800e8SDoug Rabson krb5_data_zero(&data); 253*c19800e8SDoug Rabson krb5_data_zero(&data2); 254*c19800e8SDoug Rabson memset(&req, 0, sizeof(req)); 255*c19800e8SDoug Rabson memset(&rep, 0, sizeof(rep)); 256*c19800e8SDoug Rabson 257*c19800e8SDoug Rabson if (ccache == NULL) { 258*c19800e8SDoug Rabson ret = krb5_cc_default(context, &id); 259*c19800e8SDoug Rabson if (ret) 260*c19800e8SDoug Rabson goto out; 261*c19800e8SDoug Rabson } else 262*c19800e8SDoug Rabson id = ccache; 263*c19800e8SDoug Rabson 264*c19800e8SDoug Rabson if (realm == NULL) { 265*c19800e8SDoug Rabson ret = krb5_get_default_realm(context, &r); 266*c19800e8SDoug Rabson if (ret) 267*c19800e8SDoug Rabson goto out; 268*c19800e8SDoug Rabson } else 269*c19800e8SDoug Rabson r = realm; 270*c19800e8SDoug Rabson 271*c19800e8SDoug Rabson /* 272*c19800e8SDoug Rabson * 273*c19800e8SDoug Rabson */ 274*c19800e8SDoug Rabson 275*c19800e8SDoug Rabson ret = krb5_make_principal(context, &principal, 276*c19800e8SDoug Rabson r, KRB5_DIGEST_NAME, r, NULL); 277*c19800e8SDoug Rabson if (ret) 278*c19800e8SDoug Rabson goto out; 279*c19800e8SDoug Rabson 280*c19800e8SDoug Rabson ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length, 281*c19800e8SDoug Rabson ireq, &size, ret); 282*c19800e8SDoug Rabson if (ret) { 283*c19800e8SDoug Rabson krb5_set_error_string(context, 284*c19800e8SDoug Rabson "Failed to encode digest inner request"); 285*c19800e8SDoug Rabson goto out; 286*c19800e8SDoug Rabson } 287*c19800e8SDoug Rabson if (size != data.length) 288*c19800e8SDoug Rabson krb5_abortx(context, "ASN.1 internal encoder error"); 289*c19800e8SDoug Rabson 290*c19800e8SDoug Rabson ret = krb5_mk_req_exact(context, &ac, 291*c19800e8SDoug Rabson AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED, 292*c19800e8SDoug Rabson principal, NULL, id, &req.apReq); 293*c19800e8SDoug Rabson if (ret) 294*c19800e8SDoug Rabson goto out; 295*c19800e8SDoug Rabson 296*c19800e8SDoug Rabson { 297*c19800e8SDoug Rabson krb5_keyblock *key; 298*c19800e8SDoug Rabson 299*c19800e8SDoug Rabson ret = krb5_auth_con_getlocalsubkey(context, ac, &key); 300*c19800e8SDoug Rabson if (ret) 301*c19800e8SDoug Rabson goto out; 302*c19800e8SDoug Rabson if (key == NULL) { 303*c19800e8SDoug Rabson krb5_set_error_string(context, "Digest failed to get local subkey"); 304*c19800e8SDoug Rabson ret = EINVAL; 305*c19800e8SDoug Rabson goto out; 306*c19800e8SDoug Rabson } 307*c19800e8SDoug Rabson 308*c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 0, &crypto); 309*c19800e8SDoug Rabson krb5_free_keyblock (context, key); 310*c19800e8SDoug Rabson if (ret) 311*c19800e8SDoug Rabson goto out; 312*c19800e8SDoug Rabson } 313*c19800e8SDoug Rabson 314*c19800e8SDoug Rabson ret = krb5_encrypt_EncryptedData(context, crypto, usage, 315*c19800e8SDoug Rabson data.data, data.length, 0, 316*c19800e8SDoug Rabson &req.innerReq); 317*c19800e8SDoug Rabson if (ret) 318*c19800e8SDoug Rabson goto out; 319*c19800e8SDoug Rabson 320*c19800e8SDoug Rabson krb5_data_free(&data); 321*c19800e8SDoug Rabson 322*c19800e8SDoug Rabson ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length, 323*c19800e8SDoug Rabson &req, &size, ret); 324*c19800e8SDoug Rabson if (ret) { 325*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to encode DigestREQest"); 326*c19800e8SDoug Rabson goto out; 327*c19800e8SDoug Rabson } 328*c19800e8SDoug Rabson if (size != data.length) 329*c19800e8SDoug Rabson krb5_abortx(context, "ASN.1 internal encoder error"); 330*c19800e8SDoug Rabson 331*c19800e8SDoug Rabson ret = krb5_sendto_kdc(context, &data, &r, &data2); 332*c19800e8SDoug Rabson if (ret) 333*c19800e8SDoug Rabson goto out; 334*c19800e8SDoug Rabson 335*c19800e8SDoug Rabson ret = decode_DigestREP(data2.data, data2.length, &rep, NULL); 336*c19800e8SDoug Rabson if (ret) { 337*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to parse digest response"); 338*c19800e8SDoug Rabson goto out; 339*c19800e8SDoug Rabson } 340*c19800e8SDoug Rabson 341*c19800e8SDoug Rabson { 342*c19800e8SDoug Rabson krb5_ap_rep_enc_part *repl; 343*c19800e8SDoug Rabson 344*c19800e8SDoug Rabson ret = krb5_rd_rep(context, ac, &rep.apRep, &repl); 345*c19800e8SDoug Rabson if (ret) 346*c19800e8SDoug Rabson goto out; 347*c19800e8SDoug Rabson 348*c19800e8SDoug Rabson krb5_free_ap_rep_enc_part(context, repl); 349*c19800e8SDoug Rabson } 350*c19800e8SDoug Rabson { 351*c19800e8SDoug Rabson krb5_keyblock *key; 352*c19800e8SDoug Rabson 353*c19800e8SDoug Rabson ret = krb5_auth_con_getremotesubkey(context, ac, &key); 354*c19800e8SDoug Rabson if (ret) 355*c19800e8SDoug Rabson goto out; 356*c19800e8SDoug Rabson if (key == NULL) { 357*c19800e8SDoug Rabson ret = EINVAL; 358*c19800e8SDoug Rabson krb5_set_error_string(context, 359*c19800e8SDoug Rabson "Digest reply have no remote subkey"); 360*c19800e8SDoug Rabson goto out; 361*c19800e8SDoug Rabson } 362*c19800e8SDoug Rabson 363*c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 364*c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 0, &crypto); 365*c19800e8SDoug Rabson krb5_free_keyblock (context, key); 366*c19800e8SDoug Rabson if (ret) 367*c19800e8SDoug Rabson goto out; 368*c19800e8SDoug Rabson } 369*c19800e8SDoug Rabson 370*c19800e8SDoug Rabson krb5_data_free(&data); 371*c19800e8SDoug Rabson ret = krb5_decrypt_EncryptedData(context, crypto, usage, 372*c19800e8SDoug Rabson &rep.innerRep, &data); 373*c19800e8SDoug Rabson if (ret) 374*c19800e8SDoug Rabson goto out; 375*c19800e8SDoug Rabson 376*c19800e8SDoug Rabson ret = decode_DigestRepInner(data.data, data.length, irep, NULL); 377*c19800e8SDoug Rabson if (ret) { 378*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to decode digest inner reply"); 379*c19800e8SDoug Rabson goto out; 380*c19800e8SDoug Rabson } 381*c19800e8SDoug Rabson 382*c19800e8SDoug Rabson out: 383*c19800e8SDoug Rabson if (ccache == NULL && id) 384*c19800e8SDoug Rabson krb5_cc_close(context, id); 385*c19800e8SDoug Rabson if (realm == NULL && r) 386*c19800e8SDoug Rabson free(r); 387*c19800e8SDoug Rabson if (crypto) 388*c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 389*c19800e8SDoug Rabson if (ac) 390*c19800e8SDoug Rabson krb5_auth_con_free(context, ac); 391*c19800e8SDoug Rabson if (principal) 392*c19800e8SDoug Rabson krb5_free_principal(context, principal); 393*c19800e8SDoug Rabson 394*c19800e8SDoug Rabson krb5_data_free(&data); 395*c19800e8SDoug Rabson krb5_data_free(&data2); 396*c19800e8SDoug Rabson 397*c19800e8SDoug Rabson free_DigestREQ(&req); 398*c19800e8SDoug Rabson free_DigestREP(&rep); 399*c19800e8SDoug Rabson 400*c19800e8SDoug Rabson return ret; 401*c19800e8SDoug Rabson } 402*c19800e8SDoug Rabson 403*c19800e8SDoug Rabson krb5_error_code 404*c19800e8SDoug Rabson krb5_digest_init_request(krb5_context context, 405*c19800e8SDoug Rabson krb5_digest digest, 406*c19800e8SDoug Rabson krb5_realm realm, 407*c19800e8SDoug Rabson krb5_ccache ccache) 408*c19800e8SDoug Rabson { 409*c19800e8SDoug Rabson DigestReqInner ireq; 410*c19800e8SDoug Rabson DigestRepInner irep; 411*c19800e8SDoug Rabson krb5_error_code ret; 412*c19800e8SDoug Rabson 413*c19800e8SDoug Rabson memset(&ireq, 0, sizeof(ireq)); 414*c19800e8SDoug Rabson memset(&irep, 0, sizeof(irep)); 415*c19800e8SDoug Rabson 416*c19800e8SDoug Rabson if (digest->init.type == NULL) { 417*c19800e8SDoug Rabson krb5_set_error_string(context, "Type missing from init req"); 418*c19800e8SDoug Rabson return EINVAL; 419*c19800e8SDoug Rabson } 420*c19800e8SDoug Rabson 421*c19800e8SDoug Rabson ireq.element = choice_DigestReqInner_init; 422*c19800e8SDoug Rabson ireq.u.init = digest->init; 423*c19800e8SDoug Rabson 424*c19800e8SDoug Rabson ret = digest_request(context, realm, ccache, 425*c19800e8SDoug Rabson KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 426*c19800e8SDoug Rabson if (ret) 427*c19800e8SDoug Rabson goto out; 428*c19800e8SDoug Rabson 429*c19800e8SDoug Rabson if (irep.element == choice_DigestRepInner_error) { 430*c19800e8SDoug Rabson krb5_set_error_string(context, "Digest init error: %s", 431*c19800e8SDoug Rabson irep.u.error.reason); 432*c19800e8SDoug Rabson ret = irep.u.error.code; 433*c19800e8SDoug Rabson goto out; 434*c19800e8SDoug Rabson } 435*c19800e8SDoug Rabson 436*c19800e8SDoug Rabson if (irep.element != choice_DigestRepInner_initReply) { 437*c19800e8SDoug Rabson krb5_set_error_string(context, "digest reply not an initReply"); 438*c19800e8SDoug Rabson ret = EINVAL; 439*c19800e8SDoug Rabson goto out; 440*c19800e8SDoug Rabson } 441*c19800e8SDoug Rabson 442*c19800e8SDoug Rabson ret = copy_DigestInitReply(&irep.u.initReply, &digest->initReply); 443*c19800e8SDoug Rabson if (ret) { 444*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to copy initReply"); 445*c19800e8SDoug Rabson goto out; 446*c19800e8SDoug Rabson } 447*c19800e8SDoug Rabson 448*c19800e8SDoug Rabson out: 449*c19800e8SDoug Rabson free_DigestRepInner(&irep); 450*c19800e8SDoug Rabson 451*c19800e8SDoug Rabson return ret; 452*c19800e8SDoug Rabson } 453*c19800e8SDoug Rabson 454*c19800e8SDoug Rabson 455*c19800e8SDoug Rabson krb5_error_code 456*c19800e8SDoug Rabson krb5_digest_set_client_nonce(krb5_context context, 457*c19800e8SDoug Rabson krb5_digest digest, 458*c19800e8SDoug Rabson const char *nonce) 459*c19800e8SDoug Rabson { 460*c19800e8SDoug Rabson if (digest->request.clientNonce) { 461*c19800e8SDoug Rabson krb5_set_error_string(context, "clientNonce already set"); 462*c19800e8SDoug Rabson return EINVAL; 463*c19800e8SDoug Rabson } 464*c19800e8SDoug Rabson digest->request.clientNonce = 465*c19800e8SDoug Rabson calloc(1, sizeof(*digest->request.clientNonce)); 466*c19800e8SDoug Rabson if (digest->request.clientNonce == NULL) { 467*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 468*c19800e8SDoug Rabson return ENOMEM; 469*c19800e8SDoug Rabson } 470*c19800e8SDoug Rabson *digest->request.clientNonce = strdup(nonce); 471*c19800e8SDoug Rabson if (*digest->request.clientNonce == NULL) { 472*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 473*c19800e8SDoug Rabson free(digest->request.clientNonce); 474*c19800e8SDoug Rabson digest->request.clientNonce = NULL; 475*c19800e8SDoug Rabson return ENOMEM; 476*c19800e8SDoug Rabson } 477*c19800e8SDoug Rabson return 0; 478*c19800e8SDoug Rabson } 479*c19800e8SDoug Rabson 480*c19800e8SDoug Rabson krb5_error_code 481*c19800e8SDoug Rabson krb5_digest_set_digest(krb5_context context, 482*c19800e8SDoug Rabson krb5_digest digest, 483*c19800e8SDoug Rabson const char *dgst) 484*c19800e8SDoug Rabson { 485*c19800e8SDoug Rabson if (digest->request.digest) { 486*c19800e8SDoug Rabson krb5_set_error_string(context, "digest already set"); 487*c19800e8SDoug Rabson return EINVAL; 488*c19800e8SDoug Rabson } 489*c19800e8SDoug Rabson digest->request.digest = strdup(dgst); 490*c19800e8SDoug Rabson if (digest->request.digest == NULL) { 491*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 492*c19800e8SDoug Rabson return ENOMEM; 493*c19800e8SDoug Rabson } 494*c19800e8SDoug Rabson return 0; 495*c19800e8SDoug Rabson } 496*c19800e8SDoug Rabson 497*c19800e8SDoug Rabson krb5_error_code 498*c19800e8SDoug Rabson krb5_digest_set_username(krb5_context context, 499*c19800e8SDoug Rabson krb5_digest digest, 500*c19800e8SDoug Rabson const char *username) 501*c19800e8SDoug Rabson { 502*c19800e8SDoug Rabson if (digest->request.username) { 503*c19800e8SDoug Rabson krb5_set_error_string(context, "username already set"); 504*c19800e8SDoug Rabson return EINVAL; 505*c19800e8SDoug Rabson } 506*c19800e8SDoug Rabson digest->request.username = strdup(username); 507*c19800e8SDoug Rabson if (digest->request.username == NULL) { 508*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 509*c19800e8SDoug Rabson return ENOMEM; 510*c19800e8SDoug Rabson } 511*c19800e8SDoug Rabson return 0; 512*c19800e8SDoug Rabson } 513*c19800e8SDoug Rabson 514*c19800e8SDoug Rabson krb5_error_code 515*c19800e8SDoug Rabson krb5_digest_set_authid(krb5_context context, 516*c19800e8SDoug Rabson krb5_digest digest, 517*c19800e8SDoug Rabson const char *authid) 518*c19800e8SDoug Rabson { 519*c19800e8SDoug Rabson if (digest->request.authid) { 520*c19800e8SDoug Rabson krb5_set_error_string(context, "authid already set"); 521*c19800e8SDoug Rabson return EINVAL; 522*c19800e8SDoug Rabson } 523*c19800e8SDoug Rabson digest->request.authid = malloc(sizeof(*digest->request.authid)); 524*c19800e8SDoug Rabson if (digest->request.authid == NULL) { 525*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 526*c19800e8SDoug Rabson return ENOMEM; 527*c19800e8SDoug Rabson } 528*c19800e8SDoug Rabson *digest->request.authid = strdup(authid); 529*c19800e8SDoug Rabson if (*digest->request.authid == NULL) { 530*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 531*c19800e8SDoug Rabson free(digest->request.authid); 532*c19800e8SDoug Rabson digest->request.authid = NULL; 533*c19800e8SDoug Rabson return ENOMEM; 534*c19800e8SDoug Rabson } 535*c19800e8SDoug Rabson return 0; 536*c19800e8SDoug Rabson } 537*c19800e8SDoug Rabson 538*c19800e8SDoug Rabson krb5_error_code 539*c19800e8SDoug Rabson krb5_digest_set_authentication_user(krb5_context context, 540*c19800e8SDoug Rabson krb5_digest digest, 541*c19800e8SDoug Rabson krb5_principal authentication_user) 542*c19800e8SDoug Rabson { 543*c19800e8SDoug Rabson krb5_error_code ret; 544*c19800e8SDoug Rabson 545*c19800e8SDoug Rabson if (digest->request.authentication_user) { 546*c19800e8SDoug Rabson krb5_set_error_string(context, "authentication_user already set"); 547*c19800e8SDoug Rabson return EINVAL; 548*c19800e8SDoug Rabson } 549*c19800e8SDoug Rabson ret = krb5_copy_principal(context, 550*c19800e8SDoug Rabson authentication_user, 551*c19800e8SDoug Rabson &digest->request.authentication_user); 552*c19800e8SDoug Rabson if (digest->request.authentication_user == NULL) { 553*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 554*c19800e8SDoug Rabson return ENOMEM; 555*c19800e8SDoug Rabson } 556*c19800e8SDoug Rabson return 0; 557*c19800e8SDoug Rabson } 558*c19800e8SDoug Rabson 559*c19800e8SDoug Rabson krb5_error_code 560*c19800e8SDoug Rabson krb5_digest_set_realm(krb5_context context, 561*c19800e8SDoug Rabson krb5_digest digest, 562*c19800e8SDoug Rabson const char *realm) 563*c19800e8SDoug Rabson { 564*c19800e8SDoug Rabson if (digest->request.realm) { 565*c19800e8SDoug Rabson krb5_set_error_string(context, "realm already set"); 566*c19800e8SDoug Rabson return EINVAL; 567*c19800e8SDoug Rabson } 568*c19800e8SDoug Rabson digest->request.realm = malloc(sizeof(*digest->request.realm)); 569*c19800e8SDoug Rabson if (digest->request.realm == NULL) { 570*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 571*c19800e8SDoug Rabson return ENOMEM; 572*c19800e8SDoug Rabson } 573*c19800e8SDoug Rabson *digest->request.realm = strdup(realm); 574*c19800e8SDoug Rabson if (*digest->request.realm == NULL) { 575*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 576*c19800e8SDoug Rabson free(digest->request.realm); 577*c19800e8SDoug Rabson digest->request.realm = NULL; 578*c19800e8SDoug Rabson return ENOMEM; 579*c19800e8SDoug Rabson } 580*c19800e8SDoug Rabson return 0; 581*c19800e8SDoug Rabson } 582*c19800e8SDoug Rabson 583*c19800e8SDoug Rabson krb5_error_code 584*c19800e8SDoug Rabson krb5_digest_set_method(krb5_context context, 585*c19800e8SDoug Rabson krb5_digest digest, 586*c19800e8SDoug Rabson const char *method) 587*c19800e8SDoug Rabson { 588*c19800e8SDoug Rabson if (digest->request.method) { 589*c19800e8SDoug Rabson krb5_set_error_string(context, "method already set"); 590*c19800e8SDoug Rabson return EINVAL; 591*c19800e8SDoug Rabson } 592*c19800e8SDoug Rabson digest->request.method = malloc(sizeof(*digest->request.method)); 593*c19800e8SDoug Rabson if (digest->request.method == NULL) { 594*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 595*c19800e8SDoug Rabson return ENOMEM; 596*c19800e8SDoug Rabson } 597*c19800e8SDoug Rabson *digest->request.method = strdup(method); 598*c19800e8SDoug Rabson if (*digest->request.method == NULL) { 599*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 600*c19800e8SDoug Rabson free(digest->request.method); 601*c19800e8SDoug Rabson digest->request.method = NULL; 602*c19800e8SDoug Rabson return ENOMEM; 603*c19800e8SDoug Rabson } 604*c19800e8SDoug Rabson return 0; 605*c19800e8SDoug Rabson } 606*c19800e8SDoug Rabson 607*c19800e8SDoug Rabson krb5_error_code 608*c19800e8SDoug Rabson krb5_digest_set_uri(krb5_context context, 609*c19800e8SDoug Rabson krb5_digest digest, 610*c19800e8SDoug Rabson const char *uri) 611*c19800e8SDoug Rabson { 612*c19800e8SDoug Rabson if (digest->request.uri) { 613*c19800e8SDoug Rabson krb5_set_error_string(context, "uri already set"); 614*c19800e8SDoug Rabson return EINVAL; 615*c19800e8SDoug Rabson } 616*c19800e8SDoug Rabson digest->request.uri = malloc(sizeof(*digest->request.uri)); 617*c19800e8SDoug Rabson if (digest->request.uri == NULL) { 618*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 619*c19800e8SDoug Rabson return ENOMEM; 620*c19800e8SDoug Rabson } 621*c19800e8SDoug Rabson *digest->request.uri = strdup(uri); 622*c19800e8SDoug Rabson if (*digest->request.uri == NULL) { 623*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 624*c19800e8SDoug Rabson free(digest->request.uri); 625*c19800e8SDoug Rabson digest->request.uri = NULL; 626*c19800e8SDoug Rabson return ENOMEM; 627*c19800e8SDoug Rabson } 628*c19800e8SDoug Rabson return 0; 629*c19800e8SDoug Rabson } 630*c19800e8SDoug Rabson 631*c19800e8SDoug Rabson krb5_error_code 632*c19800e8SDoug Rabson krb5_digest_set_nonceCount(krb5_context context, 633*c19800e8SDoug Rabson krb5_digest digest, 634*c19800e8SDoug Rabson const char *nonce_count) 635*c19800e8SDoug Rabson { 636*c19800e8SDoug Rabson if (digest->request.nonceCount) { 637*c19800e8SDoug Rabson krb5_set_error_string(context, "nonceCount already set"); 638*c19800e8SDoug Rabson return EINVAL; 639*c19800e8SDoug Rabson } 640*c19800e8SDoug Rabson digest->request.nonceCount = 641*c19800e8SDoug Rabson malloc(sizeof(*digest->request.nonceCount)); 642*c19800e8SDoug Rabson if (digest->request.nonceCount == NULL) { 643*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 644*c19800e8SDoug Rabson return ENOMEM; 645*c19800e8SDoug Rabson } 646*c19800e8SDoug Rabson *digest->request.nonceCount = strdup(nonce_count); 647*c19800e8SDoug Rabson if (*digest->request.nonceCount == NULL) { 648*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 649*c19800e8SDoug Rabson free(digest->request.nonceCount); 650*c19800e8SDoug Rabson digest->request.nonceCount = NULL; 651*c19800e8SDoug Rabson return ENOMEM; 652*c19800e8SDoug Rabson } 653*c19800e8SDoug Rabson return 0; 654*c19800e8SDoug Rabson } 655*c19800e8SDoug Rabson 656*c19800e8SDoug Rabson krb5_error_code 657*c19800e8SDoug Rabson krb5_digest_set_qop(krb5_context context, 658*c19800e8SDoug Rabson krb5_digest digest, 659*c19800e8SDoug Rabson const char *qop) 660*c19800e8SDoug Rabson { 661*c19800e8SDoug Rabson if (digest->request.qop) { 662*c19800e8SDoug Rabson krb5_set_error_string(context, "qop already set"); 663*c19800e8SDoug Rabson return EINVAL; 664*c19800e8SDoug Rabson } 665*c19800e8SDoug Rabson digest->request.qop = malloc(sizeof(*digest->request.qop)); 666*c19800e8SDoug Rabson if (digest->request.qop == NULL) { 667*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 668*c19800e8SDoug Rabson return ENOMEM; 669*c19800e8SDoug Rabson } 670*c19800e8SDoug Rabson *digest->request.qop = strdup(qop); 671*c19800e8SDoug Rabson if (*digest->request.qop == NULL) { 672*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 673*c19800e8SDoug Rabson free(digest->request.qop); 674*c19800e8SDoug Rabson digest->request.qop = NULL; 675*c19800e8SDoug Rabson return ENOMEM; 676*c19800e8SDoug Rabson } 677*c19800e8SDoug Rabson return 0; 678*c19800e8SDoug Rabson } 679*c19800e8SDoug Rabson 680*c19800e8SDoug Rabson int 681*c19800e8SDoug Rabson krb5_digest_set_responseData(krb5_context context, 682*c19800e8SDoug Rabson krb5_digest digest, 683*c19800e8SDoug Rabson const char *response) 684*c19800e8SDoug Rabson { 685*c19800e8SDoug Rabson digest->request.responseData = strdup(response); 686*c19800e8SDoug Rabson if (digest->request.responseData == NULL) { 687*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 688*c19800e8SDoug Rabson return ENOMEM; 689*c19800e8SDoug Rabson } 690*c19800e8SDoug Rabson return 0; 691*c19800e8SDoug Rabson } 692*c19800e8SDoug Rabson 693*c19800e8SDoug Rabson krb5_error_code 694*c19800e8SDoug Rabson krb5_digest_request(krb5_context context, 695*c19800e8SDoug Rabson krb5_digest digest, 696*c19800e8SDoug Rabson krb5_realm realm, 697*c19800e8SDoug Rabson krb5_ccache ccache) 698*c19800e8SDoug Rabson { 699*c19800e8SDoug Rabson DigestReqInner ireq; 700*c19800e8SDoug Rabson DigestRepInner irep; 701*c19800e8SDoug Rabson krb5_error_code ret; 702*c19800e8SDoug Rabson 703*c19800e8SDoug Rabson memset(&ireq, 0, sizeof(ireq)); 704*c19800e8SDoug Rabson memset(&irep, 0, sizeof(irep)); 705*c19800e8SDoug Rabson 706*c19800e8SDoug Rabson ireq.element = choice_DigestReqInner_digestRequest; 707*c19800e8SDoug Rabson ireq.u.digestRequest = digest->request; 708*c19800e8SDoug Rabson 709*c19800e8SDoug Rabson if (digest->request.type == NULL) { 710*c19800e8SDoug Rabson if (digest->init.type == NULL) { 711*c19800e8SDoug Rabson krb5_set_error_string(context, "Type missing from req"); 712*c19800e8SDoug Rabson return EINVAL; 713*c19800e8SDoug Rabson } 714*c19800e8SDoug Rabson ireq.u.digestRequest.type = digest->init.type; 715*c19800e8SDoug Rabson } 716*c19800e8SDoug Rabson 717*c19800e8SDoug Rabson if (ireq.u.digestRequest.digest == NULL) 718*c19800e8SDoug Rabson ireq.u.digestRequest.digest = "md5"; 719*c19800e8SDoug Rabson 720*c19800e8SDoug Rabson ret = digest_request(context, realm, ccache, 721*c19800e8SDoug Rabson KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 722*c19800e8SDoug Rabson if (ret) 723*c19800e8SDoug Rabson return ret; 724*c19800e8SDoug Rabson 725*c19800e8SDoug Rabson if (irep.element == choice_DigestRepInner_error) { 726*c19800e8SDoug Rabson krb5_set_error_string(context, "Digest response error: %s", 727*c19800e8SDoug Rabson irep.u.error.reason); 728*c19800e8SDoug Rabson ret = irep.u.error.code; 729*c19800e8SDoug Rabson goto out; 730*c19800e8SDoug Rabson } 731*c19800e8SDoug Rabson 732*c19800e8SDoug Rabson if (irep.element != choice_DigestRepInner_response) { 733*c19800e8SDoug Rabson krb5_set_error_string(context, "digest reply not an DigestResponse"); 734*c19800e8SDoug Rabson ret = EINVAL; 735*c19800e8SDoug Rabson goto out; 736*c19800e8SDoug Rabson } 737*c19800e8SDoug Rabson 738*c19800e8SDoug Rabson ret = copy_DigestResponse(&irep.u.response, &digest->response); 739*c19800e8SDoug Rabson if (ret) { 740*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to copy initReply"); 741*c19800e8SDoug Rabson goto out; 742*c19800e8SDoug Rabson } 743*c19800e8SDoug Rabson 744*c19800e8SDoug Rabson out: 745*c19800e8SDoug Rabson free_DigestRepInner(&irep); 746*c19800e8SDoug Rabson 747*c19800e8SDoug Rabson return ret; 748*c19800e8SDoug Rabson } 749*c19800e8SDoug Rabson 750*c19800e8SDoug Rabson krb5_boolean 751*c19800e8SDoug Rabson krb5_digest_rep_get_status(krb5_context context, 752*c19800e8SDoug Rabson krb5_digest digest) 753*c19800e8SDoug Rabson { 754*c19800e8SDoug Rabson return digest->response.success ? TRUE : FALSE; 755*c19800e8SDoug Rabson } 756*c19800e8SDoug Rabson 757*c19800e8SDoug Rabson const char * 758*c19800e8SDoug Rabson krb5_digest_get_rsp(krb5_context context, 759*c19800e8SDoug Rabson krb5_digest digest) 760*c19800e8SDoug Rabson { 761*c19800e8SDoug Rabson if (digest->response.rsp == NULL) 762*c19800e8SDoug Rabson return NULL; 763*c19800e8SDoug Rabson return *digest->response.rsp; 764*c19800e8SDoug Rabson } 765*c19800e8SDoug Rabson 766*c19800e8SDoug Rabson krb5_error_code 767*c19800e8SDoug Rabson krb5_digest_get_tickets(krb5_context context, 768*c19800e8SDoug Rabson krb5_digest digest, 769*c19800e8SDoug Rabson Ticket **tickets) 770*c19800e8SDoug Rabson { 771*c19800e8SDoug Rabson *tickets = NULL; 772*c19800e8SDoug Rabson return 0; 773*c19800e8SDoug Rabson } 774*c19800e8SDoug Rabson 775*c19800e8SDoug Rabson 776*c19800e8SDoug Rabson krb5_error_code 777*c19800e8SDoug Rabson krb5_digest_get_client_binding(krb5_context context, 778*c19800e8SDoug Rabson krb5_digest digest, 779*c19800e8SDoug Rabson char **type, 780*c19800e8SDoug Rabson char **binding) 781*c19800e8SDoug Rabson { 782*c19800e8SDoug Rabson if (digest->response.channel) { 783*c19800e8SDoug Rabson *type = strdup(digest->response.channel->cb_type); 784*c19800e8SDoug Rabson *binding = strdup(digest->response.channel->cb_binding); 785*c19800e8SDoug Rabson if (*type == NULL || *binding == NULL) { 786*c19800e8SDoug Rabson free(*type); 787*c19800e8SDoug Rabson free(*binding); 788*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 789*c19800e8SDoug Rabson return ENOMEM; 790*c19800e8SDoug Rabson } 791*c19800e8SDoug Rabson } else { 792*c19800e8SDoug Rabson *type = NULL; 793*c19800e8SDoug Rabson *binding = NULL; 794*c19800e8SDoug Rabson } 795*c19800e8SDoug Rabson return 0; 796*c19800e8SDoug Rabson } 797*c19800e8SDoug Rabson 798*c19800e8SDoug Rabson krb5_error_code 799*c19800e8SDoug Rabson krb5_digest_get_session_key(krb5_context context, 800*c19800e8SDoug Rabson krb5_digest digest, 801*c19800e8SDoug Rabson krb5_data *data) 802*c19800e8SDoug Rabson { 803*c19800e8SDoug Rabson krb5_error_code ret; 804*c19800e8SDoug Rabson 805*c19800e8SDoug Rabson krb5_data_zero(data); 806*c19800e8SDoug Rabson if (digest->response.session_key == NULL) 807*c19800e8SDoug Rabson return 0; 808*c19800e8SDoug Rabson ret = der_copy_octet_string(digest->response.session_key, data); 809*c19800e8SDoug Rabson if (ret) 810*c19800e8SDoug Rabson krb5_clear_error_string(context); 811*c19800e8SDoug Rabson 812*c19800e8SDoug Rabson return ret; 813*c19800e8SDoug Rabson } 814*c19800e8SDoug Rabson 815*c19800e8SDoug Rabson struct krb5_ntlm_data { 816*c19800e8SDoug Rabson NTLMInit init; 817*c19800e8SDoug Rabson NTLMInitReply initReply; 818*c19800e8SDoug Rabson NTLMRequest request; 819*c19800e8SDoug Rabson NTLMResponse response; 820*c19800e8SDoug Rabson }; 821*c19800e8SDoug Rabson 822*c19800e8SDoug Rabson krb5_error_code 823*c19800e8SDoug Rabson krb5_ntlm_alloc(krb5_context context, 824*c19800e8SDoug Rabson krb5_ntlm *ntlm) 825*c19800e8SDoug Rabson { 826*c19800e8SDoug Rabson *ntlm = calloc(1, sizeof(**ntlm)); 827*c19800e8SDoug Rabson if (*ntlm == NULL) { 828*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 829*c19800e8SDoug Rabson return ENOMEM; 830*c19800e8SDoug Rabson } 831*c19800e8SDoug Rabson return 0; 832*c19800e8SDoug Rabson } 833*c19800e8SDoug Rabson 834*c19800e8SDoug Rabson krb5_error_code 835*c19800e8SDoug Rabson krb5_ntlm_free(krb5_context context, krb5_ntlm ntlm) 836*c19800e8SDoug Rabson { 837*c19800e8SDoug Rabson free_NTLMInit(&ntlm->init); 838*c19800e8SDoug Rabson free_NTLMInitReply(&ntlm->initReply); 839*c19800e8SDoug Rabson free_NTLMRequest(&ntlm->request); 840*c19800e8SDoug Rabson free_NTLMResponse(&ntlm->response); 841*c19800e8SDoug Rabson memset(ntlm, 0, sizeof(*ntlm)); 842*c19800e8SDoug Rabson free(ntlm); 843*c19800e8SDoug Rabson return 0; 844*c19800e8SDoug Rabson } 845*c19800e8SDoug Rabson 846*c19800e8SDoug Rabson 847*c19800e8SDoug Rabson krb5_error_code 848*c19800e8SDoug Rabson krb5_ntlm_init_request(krb5_context context, 849*c19800e8SDoug Rabson krb5_ntlm ntlm, 850*c19800e8SDoug Rabson krb5_realm realm, 851*c19800e8SDoug Rabson krb5_ccache ccache, 852*c19800e8SDoug Rabson uint32_t flags, 853*c19800e8SDoug Rabson const char *hostname, 854*c19800e8SDoug Rabson const char *domainname) 855*c19800e8SDoug Rabson { 856*c19800e8SDoug Rabson DigestReqInner ireq; 857*c19800e8SDoug Rabson DigestRepInner irep; 858*c19800e8SDoug Rabson krb5_error_code ret; 859*c19800e8SDoug Rabson 860*c19800e8SDoug Rabson memset(&ireq, 0, sizeof(ireq)); 861*c19800e8SDoug Rabson memset(&irep, 0, sizeof(irep)); 862*c19800e8SDoug Rabson 863*c19800e8SDoug Rabson ntlm->init.flags = flags; 864*c19800e8SDoug Rabson if (hostname) { 865*c19800e8SDoug Rabson ALLOC(ntlm->init.hostname, 1); 866*c19800e8SDoug Rabson *ntlm->init.hostname = strdup(hostname); 867*c19800e8SDoug Rabson } 868*c19800e8SDoug Rabson if (domainname) { 869*c19800e8SDoug Rabson ALLOC(ntlm->init.domain, 1); 870*c19800e8SDoug Rabson *ntlm->init.domain = strdup(domainname); 871*c19800e8SDoug Rabson } 872*c19800e8SDoug Rabson 873*c19800e8SDoug Rabson ireq.element = choice_DigestReqInner_ntlmInit; 874*c19800e8SDoug Rabson ireq.u.ntlmInit = ntlm->init; 875*c19800e8SDoug Rabson 876*c19800e8SDoug Rabson ret = digest_request(context, realm, ccache, 877*c19800e8SDoug Rabson KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 878*c19800e8SDoug Rabson if (ret) 879*c19800e8SDoug Rabson goto out; 880*c19800e8SDoug Rabson 881*c19800e8SDoug Rabson if (irep.element == choice_DigestRepInner_error) { 882*c19800e8SDoug Rabson krb5_set_error_string(context, "Digest init error: %s", 883*c19800e8SDoug Rabson irep.u.error.reason); 884*c19800e8SDoug Rabson ret = irep.u.error.code; 885*c19800e8SDoug Rabson goto out; 886*c19800e8SDoug Rabson } 887*c19800e8SDoug Rabson 888*c19800e8SDoug Rabson if (irep.element != choice_DigestRepInner_ntlmInitReply) { 889*c19800e8SDoug Rabson krb5_set_error_string(context, "ntlm reply not an initReply"); 890*c19800e8SDoug Rabson ret = EINVAL; 891*c19800e8SDoug Rabson goto out; 892*c19800e8SDoug Rabson } 893*c19800e8SDoug Rabson 894*c19800e8SDoug Rabson ret = copy_NTLMInitReply(&irep.u.ntlmInitReply, &ntlm->initReply); 895*c19800e8SDoug Rabson if (ret) { 896*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to copy initReply"); 897*c19800e8SDoug Rabson goto out; 898*c19800e8SDoug Rabson } 899*c19800e8SDoug Rabson 900*c19800e8SDoug Rabson out: 901*c19800e8SDoug Rabson free_DigestRepInner(&irep); 902*c19800e8SDoug Rabson 903*c19800e8SDoug Rabson return ret; 904*c19800e8SDoug Rabson } 905*c19800e8SDoug Rabson 906*c19800e8SDoug Rabson krb5_error_code 907*c19800e8SDoug Rabson krb5_ntlm_init_get_flags(krb5_context context, 908*c19800e8SDoug Rabson krb5_ntlm ntlm, 909*c19800e8SDoug Rabson uint32_t *flags) 910*c19800e8SDoug Rabson { 911*c19800e8SDoug Rabson *flags = ntlm->initReply.flags; 912*c19800e8SDoug Rabson return 0; 913*c19800e8SDoug Rabson } 914*c19800e8SDoug Rabson 915*c19800e8SDoug Rabson krb5_error_code 916*c19800e8SDoug Rabson krb5_ntlm_init_get_challange(krb5_context context, 917*c19800e8SDoug Rabson krb5_ntlm ntlm, 918*c19800e8SDoug Rabson krb5_data *challange) 919*c19800e8SDoug Rabson { 920*c19800e8SDoug Rabson krb5_error_code ret; 921*c19800e8SDoug Rabson 922*c19800e8SDoug Rabson ret = der_copy_octet_string(&ntlm->initReply.challange, challange); 923*c19800e8SDoug Rabson if (ret) 924*c19800e8SDoug Rabson krb5_clear_error_string(context); 925*c19800e8SDoug Rabson 926*c19800e8SDoug Rabson return ret; 927*c19800e8SDoug Rabson } 928*c19800e8SDoug Rabson 929*c19800e8SDoug Rabson krb5_error_code 930*c19800e8SDoug Rabson krb5_ntlm_init_get_opaque(krb5_context context, 931*c19800e8SDoug Rabson krb5_ntlm ntlm, 932*c19800e8SDoug Rabson krb5_data *opaque) 933*c19800e8SDoug Rabson { 934*c19800e8SDoug Rabson krb5_error_code ret; 935*c19800e8SDoug Rabson 936*c19800e8SDoug Rabson ret = der_copy_octet_string(&ntlm->initReply.opaque, opaque); 937*c19800e8SDoug Rabson if (ret) 938*c19800e8SDoug Rabson krb5_clear_error_string(context); 939*c19800e8SDoug Rabson 940*c19800e8SDoug Rabson return ret; 941*c19800e8SDoug Rabson } 942*c19800e8SDoug Rabson 943*c19800e8SDoug Rabson krb5_error_code 944*c19800e8SDoug Rabson krb5_ntlm_init_get_targetname(krb5_context context, 945*c19800e8SDoug Rabson krb5_ntlm ntlm, 946*c19800e8SDoug Rabson char **name) 947*c19800e8SDoug Rabson { 948*c19800e8SDoug Rabson *name = strdup(ntlm->initReply.targetname); 949*c19800e8SDoug Rabson if (*name == NULL) { 950*c19800e8SDoug Rabson krb5_clear_error_string(context); 951*c19800e8SDoug Rabson return ENOMEM; 952*c19800e8SDoug Rabson } 953*c19800e8SDoug Rabson return 0; 954*c19800e8SDoug Rabson } 955*c19800e8SDoug Rabson 956*c19800e8SDoug Rabson krb5_error_code 957*c19800e8SDoug Rabson krb5_ntlm_init_get_targetinfo(krb5_context context, 958*c19800e8SDoug Rabson krb5_ntlm ntlm, 959*c19800e8SDoug Rabson krb5_data *data) 960*c19800e8SDoug Rabson { 961*c19800e8SDoug Rabson krb5_error_code ret; 962*c19800e8SDoug Rabson 963*c19800e8SDoug Rabson if (ntlm->initReply.targetinfo == NULL) { 964*c19800e8SDoug Rabson krb5_data_zero(data); 965*c19800e8SDoug Rabson return 0; 966*c19800e8SDoug Rabson } 967*c19800e8SDoug Rabson 968*c19800e8SDoug Rabson ret = krb5_data_copy(data, 969*c19800e8SDoug Rabson ntlm->initReply.targetinfo->data, 970*c19800e8SDoug Rabson ntlm->initReply.targetinfo->length); 971*c19800e8SDoug Rabson if (ret) { 972*c19800e8SDoug Rabson krb5_clear_error_string(context); 973*c19800e8SDoug Rabson return ret; 974*c19800e8SDoug Rabson } 975*c19800e8SDoug Rabson return 0; 976*c19800e8SDoug Rabson } 977*c19800e8SDoug Rabson 978*c19800e8SDoug Rabson 979*c19800e8SDoug Rabson krb5_error_code 980*c19800e8SDoug Rabson krb5_ntlm_request(krb5_context context, 981*c19800e8SDoug Rabson krb5_ntlm ntlm, 982*c19800e8SDoug Rabson krb5_realm realm, 983*c19800e8SDoug Rabson krb5_ccache ccache) 984*c19800e8SDoug Rabson { 985*c19800e8SDoug Rabson DigestReqInner ireq; 986*c19800e8SDoug Rabson DigestRepInner irep; 987*c19800e8SDoug Rabson krb5_error_code ret; 988*c19800e8SDoug Rabson 989*c19800e8SDoug Rabson memset(&ireq, 0, sizeof(ireq)); 990*c19800e8SDoug Rabson memset(&irep, 0, sizeof(irep)); 991*c19800e8SDoug Rabson 992*c19800e8SDoug Rabson ireq.element = choice_DigestReqInner_ntlmRequest; 993*c19800e8SDoug Rabson ireq.u.ntlmRequest = ntlm->request; 994*c19800e8SDoug Rabson 995*c19800e8SDoug Rabson ret = digest_request(context, realm, ccache, 996*c19800e8SDoug Rabson KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 997*c19800e8SDoug Rabson if (ret) 998*c19800e8SDoug Rabson return ret; 999*c19800e8SDoug Rabson 1000*c19800e8SDoug Rabson if (irep.element == choice_DigestRepInner_error) { 1001*c19800e8SDoug Rabson krb5_set_error_string(context, "NTLM response error: %s", 1002*c19800e8SDoug Rabson irep.u.error.reason); 1003*c19800e8SDoug Rabson ret = irep.u.error.code; 1004*c19800e8SDoug Rabson goto out; 1005*c19800e8SDoug Rabson } 1006*c19800e8SDoug Rabson 1007*c19800e8SDoug Rabson if (irep.element != choice_DigestRepInner_ntlmResponse) { 1008*c19800e8SDoug Rabson krb5_set_error_string(context, "NTLM reply not an NTLMResponse"); 1009*c19800e8SDoug Rabson ret = EINVAL; 1010*c19800e8SDoug Rabson goto out; 1011*c19800e8SDoug Rabson } 1012*c19800e8SDoug Rabson 1013*c19800e8SDoug Rabson ret = copy_NTLMResponse(&irep.u.ntlmResponse, &ntlm->response); 1014*c19800e8SDoug Rabson if (ret) { 1015*c19800e8SDoug Rabson krb5_set_error_string(context, "Failed to copy NTLMResponse"); 1016*c19800e8SDoug Rabson goto out; 1017*c19800e8SDoug Rabson } 1018*c19800e8SDoug Rabson 1019*c19800e8SDoug Rabson out: 1020*c19800e8SDoug Rabson free_DigestRepInner(&irep); 1021*c19800e8SDoug Rabson 1022*c19800e8SDoug Rabson return ret; 1023*c19800e8SDoug Rabson } 1024*c19800e8SDoug Rabson 1025*c19800e8SDoug Rabson krb5_error_code 1026*c19800e8SDoug Rabson krb5_ntlm_req_set_flags(krb5_context context, 1027*c19800e8SDoug Rabson krb5_ntlm ntlm, 1028*c19800e8SDoug Rabson uint32_t flags) 1029*c19800e8SDoug Rabson { 1030*c19800e8SDoug Rabson ntlm->request.flags = flags; 1031*c19800e8SDoug Rabson return 0; 1032*c19800e8SDoug Rabson } 1033*c19800e8SDoug Rabson 1034*c19800e8SDoug Rabson krb5_error_code 1035*c19800e8SDoug Rabson krb5_ntlm_req_set_username(krb5_context context, 1036*c19800e8SDoug Rabson krb5_ntlm ntlm, 1037*c19800e8SDoug Rabson const char *username) 1038*c19800e8SDoug Rabson { 1039*c19800e8SDoug Rabson ntlm->request.username = strdup(username); 1040*c19800e8SDoug Rabson if (ntlm->request.username == NULL) { 1041*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1042*c19800e8SDoug Rabson return ENOMEM; 1043*c19800e8SDoug Rabson } 1044*c19800e8SDoug Rabson return 0; 1045*c19800e8SDoug Rabson } 1046*c19800e8SDoug Rabson 1047*c19800e8SDoug Rabson krb5_error_code 1048*c19800e8SDoug Rabson krb5_ntlm_req_set_targetname(krb5_context context, 1049*c19800e8SDoug Rabson krb5_ntlm ntlm, 1050*c19800e8SDoug Rabson const char *targetname) 1051*c19800e8SDoug Rabson { 1052*c19800e8SDoug Rabson ntlm->request.targetname = strdup(targetname); 1053*c19800e8SDoug Rabson if (ntlm->request.targetname == NULL) { 1054*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1055*c19800e8SDoug Rabson return ENOMEM; 1056*c19800e8SDoug Rabson } 1057*c19800e8SDoug Rabson return 0; 1058*c19800e8SDoug Rabson } 1059*c19800e8SDoug Rabson 1060*c19800e8SDoug Rabson krb5_error_code 1061*c19800e8SDoug Rabson krb5_ntlm_req_set_lm(krb5_context context, 1062*c19800e8SDoug Rabson krb5_ntlm ntlm, 1063*c19800e8SDoug Rabson void *hash, size_t len) 1064*c19800e8SDoug Rabson { 1065*c19800e8SDoug Rabson ntlm->request.lm.data = malloc(len); 1066*c19800e8SDoug Rabson if (ntlm->request.lm.data == NULL) { 1067*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1068*c19800e8SDoug Rabson return ENOMEM; 1069*c19800e8SDoug Rabson } 1070*c19800e8SDoug Rabson ntlm->request.lm.length = len; 1071*c19800e8SDoug Rabson memcpy(ntlm->request.lm.data, hash, len); 1072*c19800e8SDoug Rabson return 0; 1073*c19800e8SDoug Rabson } 1074*c19800e8SDoug Rabson 1075*c19800e8SDoug Rabson krb5_error_code 1076*c19800e8SDoug Rabson krb5_ntlm_req_set_ntlm(krb5_context context, 1077*c19800e8SDoug Rabson krb5_ntlm ntlm, 1078*c19800e8SDoug Rabson void *hash, size_t len) 1079*c19800e8SDoug Rabson { 1080*c19800e8SDoug Rabson ntlm->request.ntlm.data = malloc(len); 1081*c19800e8SDoug Rabson if (ntlm->request.ntlm.data == NULL) { 1082*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1083*c19800e8SDoug Rabson return ENOMEM; 1084*c19800e8SDoug Rabson } 1085*c19800e8SDoug Rabson ntlm->request.ntlm.length = len; 1086*c19800e8SDoug Rabson memcpy(ntlm->request.ntlm.data, hash, len); 1087*c19800e8SDoug Rabson return 0; 1088*c19800e8SDoug Rabson } 1089*c19800e8SDoug Rabson 1090*c19800e8SDoug Rabson krb5_error_code 1091*c19800e8SDoug Rabson krb5_ntlm_req_set_opaque(krb5_context context, 1092*c19800e8SDoug Rabson krb5_ntlm ntlm, 1093*c19800e8SDoug Rabson krb5_data *opaque) 1094*c19800e8SDoug Rabson { 1095*c19800e8SDoug Rabson ntlm->request.opaque.data = malloc(opaque->length); 1096*c19800e8SDoug Rabson if (ntlm->request.opaque.data == NULL) { 1097*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1098*c19800e8SDoug Rabson return ENOMEM; 1099*c19800e8SDoug Rabson } 1100*c19800e8SDoug Rabson ntlm->request.opaque.length = opaque->length; 1101*c19800e8SDoug Rabson memcpy(ntlm->request.opaque.data, opaque->data, opaque->length); 1102*c19800e8SDoug Rabson return 0; 1103*c19800e8SDoug Rabson } 1104*c19800e8SDoug Rabson 1105*c19800e8SDoug Rabson krb5_error_code 1106*c19800e8SDoug Rabson krb5_ntlm_req_set_session(krb5_context context, 1107*c19800e8SDoug Rabson krb5_ntlm ntlm, 1108*c19800e8SDoug Rabson void *sessionkey, size_t length) 1109*c19800e8SDoug Rabson { 1110*c19800e8SDoug Rabson ntlm->request.sessionkey = calloc(1, sizeof(*ntlm->request.sessionkey)); 1111*c19800e8SDoug Rabson if (ntlm->request.sessionkey == NULL) { 1112*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1113*c19800e8SDoug Rabson return ENOMEM; 1114*c19800e8SDoug Rabson } 1115*c19800e8SDoug Rabson ntlm->request.sessionkey->data = malloc(length); 1116*c19800e8SDoug Rabson if (ntlm->request.sessionkey->data == NULL) { 1117*c19800e8SDoug Rabson krb5_set_error_string(context, "out of memory"); 1118*c19800e8SDoug Rabson return ENOMEM; 1119*c19800e8SDoug Rabson } 1120*c19800e8SDoug Rabson memcpy(ntlm->request.sessionkey->data, sessionkey, length); 1121*c19800e8SDoug Rabson ntlm->request.sessionkey->length = length; 1122*c19800e8SDoug Rabson return 0; 1123*c19800e8SDoug Rabson } 1124*c19800e8SDoug Rabson 1125*c19800e8SDoug Rabson krb5_boolean 1126*c19800e8SDoug Rabson krb5_ntlm_rep_get_status(krb5_context context, 1127*c19800e8SDoug Rabson krb5_ntlm ntlm) 1128*c19800e8SDoug Rabson { 1129*c19800e8SDoug Rabson return ntlm->response.success ? TRUE : FALSE; 1130*c19800e8SDoug Rabson } 1131*c19800e8SDoug Rabson 1132*c19800e8SDoug Rabson krb5_error_code 1133*c19800e8SDoug Rabson krb5_ntlm_rep_get_sessionkey(krb5_context context, 1134*c19800e8SDoug Rabson krb5_ntlm ntlm, 1135*c19800e8SDoug Rabson krb5_data *data) 1136*c19800e8SDoug Rabson { 1137*c19800e8SDoug Rabson if (ntlm->response.sessionkey == NULL) { 1138*c19800e8SDoug Rabson krb5_set_error_string(context, "no ntlm session key"); 1139*c19800e8SDoug Rabson return EINVAL; 1140*c19800e8SDoug Rabson } 1141*c19800e8SDoug Rabson krb5_clear_error_string(context); 1142*c19800e8SDoug Rabson return krb5_data_copy(data, 1143*c19800e8SDoug Rabson ntlm->response.sessionkey->data, 1144*c19800e8SDoug Rabson ntlm->response.sessionkey->length); 1145*c19800e8SDoug Rabson } 1146*c19800e8SDoug Rabson 1147*c19800e8SDoug Rabson /** 1148*c19800e8SDoug Rabson * Get the supported/allowed mechanism for this principal. 1149*c19800e8SDoug Rabson * 1150*c19800e8SDoug Rabson * @param context A Keberos context. 1151*c19800e8SDoug Rabson * @param realm The realm of the KDC. 1152*c19800e8SDoug Rabson * @param ccache The credential cache to use when talking to the KDC. 1153*c19800e8SDoug Rabson * @param flags The supported mechanism. 1154*c19800e8SDoug Rabson * 1155*c19800e8SDoug Rabson * @return Return an error code or 0. 1156*c19800e8SDoug Rabson * 1157*c19800e8SDoug Rabson * @ingroup krb5_digest 1158*c19800e8SDoug Rabson */ 1159*c19800e8SDoug Rabson 1160*c19800e8SDoug Rabson krb5_error_code 1161*c19800e8SDoug Rabson krb5_digest_probe(krb5_context context, 1162*c19800e8SDoug Rabson krb5_realm realm, 1163*c19800e8SDoug Rabson krb5_ccache ccache, 1164*c19800e8SDoug Rabson unsigned *flags) 1165*c19800e8SDoug Rabson { 1166*c19800e8SDoug Rabson DigestReqInner ireq; 1167*c19800e8SDoug Rabson DigestRepInner irep; 1168*c19800e8SDoug Rabson krb5_error_code ret; 1169*c19800e8SDoug Rabson 1170*c19800e8SDoug Rabson memset(&ireq, 0, sizeof(ireq)); 1171*c19800e8SDoug Rabson memset(&irep, 0, sizeof(irep)); 1172*c19800e8SDoug Rabson 1173*c19800e8SDoug Rabson ireq.element = choice_DigestReqInner_supportedMechs; 1174*c19800e8SDoug Rabson 1175*c19800e8SDoug Rabson ret = digest_request(context, realm, ccache, 1176*c19800e8SDoug Rabson KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); 1177*c19800e8SDoug Rabson if (ret) 1178*c19800e8SDoug Rabson goto out; 1179*c19800e8SDoug Rabson 1180*c19800e8SDoug Rabson if (irep.element == choice_DigestRepInner_error) { 1181*c19800e8SDoug Rabson krb5_set_error_string(context, "Digest probe error: %s", 1182*c19800e8SDoug Rabson irep.u.error.reason); 1183*c19800e8SDoug Rabson ret = irep.u.error.code; 1184*c19800e8SDoug Rabson goto out; 1185*c19800e8SDoug Rabson } 1186*c19800e8SDoug Rabson 1187*c19800e8SDoug Rabson if (irep.element != choice_DigestRepInner_supportedMechs) { 1188*c19800e8SDoug Rabson krb5_set_error_string(context, "Digest reply not an probe"); 1189*c19800e8SDoug Rabson ret = EINVAL; 1190*c19800e8SDoug Rabson goto out; 1191*c19800e8SDoug Rabson } 1192*c19800e8SDoug Rabson 1193*c19800e8SDoug Rabson *flags = DigestTypes2int(irep.u.supportedMechs); 1194*c19800e8SDoug Rabson 1195*c19800e8SDoug Rabson out: 1196*c19800e8SDoug Rabson free_DigestRepInner(&irep); 1197*c19800e8SDoug Rabson 1198*c19800e8SDoug Rabson return ret; 1199*c19800e8SDoug Rabson } 1200