Path: blob/main/crypto/heimdal/lib/kafs/afskrb5.c
108106 views
/*1* Copyright (c) 1995-2003 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "kafs_locl.h"3435struct krb5_kafs_data {36krb5_context context;37krb5_ccache id;38krb5_const_realm realm;39};4041enum {42KAFS_RXKAD_2B_KVNO = 213,43KAFS_RXKAD_K5_KVNO = 25644};4546static int47v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524)48{49int kvno, ret;5051kt->ticket = NULL;5253/* check if des key */54if (cred->session.keyvalue.length != 8)55return EINVAL;5657if (local524) {58Ticket t;59unsigned char *buf;60size_t buf_len;61size_t len;6263kvno = KAFS_RXKAD_2B_KVNO;6465ret = decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);66if (ret)67return ret;68if (t.tkt_vno != 5)69return -1;7071ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_len, &t.enc_part,72&len, ret);73free_Ticket(&t);74if (ret)75return ret;76if(buf_len != len) {77free(buf);78return KRB5KRB_ERR_GENERIC;79}8081kt->ticket = buf;82kt->ticket_len = buf_len;8384} else {85kvno = KAFS_RXKAD_K5_KVNO;86kt->ticket = malloc(cred->ticket.length);87if (kt->ticket == NULL)88return ENOMEM;89kt->ticket_len = cred->ticket.length;90memcpy(kt->ticket, cred->ticket.data, kt->ticket_len);91}929394/*95* Build a struct ClearToken96*/9798kt->ct.AuthHandle = kvno;99memcpy(kt->ct.HandShakeKey, cred->session.keyvalue.data, 8);100kt->ct.ViceId = uid;101kt->ct.BeginTimestamp = cred->times.starttime;102kt->ct.EndTimestamp = cred->times.endtime;103104_kafs_fixup_viceid(&kt->ct, uid);105106return 0;107}108109static krb5_error_code110v5_convert(krb5_context context, krb5_ccache id,111krb5_creds *cred, uid_t uid,112const char *cell,113struct kafs_token *kt)114{115krb5_error_code ret;116char *c, *val;117118c = strdup(cell);119if (c == NULL)120return ENOMEM;121_kafs_foldup(c, c);122krb5_appdefault_string (context, "libkafs",123c,124"afs-use-524", "2b", &val);125free(c);126127if (strcasecmp(val, "local") == 0 ||128strcasecmp(val, "2b") == 0)129ret = v5_to_kt(cred, uid, kt, 1);130else131ret = v5_to_kt(cred, uid, kt, 0);132133free(val);134return ret;135}136137138/*139*140*/141142static int143get_cred(struct kafs_data *data, const char *name, const char *inst,144const char *realm, uid_t uid, struct kafs_token *kt)145{146krb5_error_code ret;147krb5_creds in_creds, *out_creds;148struct krb5_kafs_data *d = data->data;149int invalid;150151memset(&in_creds, 0, sizeof(in_creds));152153ret = krb5_make_principal(d->context, &in_creds.server,154realm, name, inst, NULL);155if(ret)156return ret;157ret = krb5_cc_get_principal(d->context, d->id, &in_creds.client);158if(ret){159krb5_free_principal(d->context, in_creds.server);160return ret;161}162163in_creds.session.keytype = ETYPE_DES_CBC_CRC;164165/* check if des is disable, and in that case enable it for afs */166invalid = krb5_enctype_valid(d->context, in_creds.session.keytype);167if (invalid)168krb5_enctype_enable(d->context, in_creds.session.keytype);169170ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds);171if (ret) {172in_creds.session.keytype = ETYPE_DES_CBC_MD5;173ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds);174}175176if (invalid)177krb5_enctype_disable(d->context, in_creds.session.keytype);178179krb5_free_principal(d->context, in_creds.server);180krb5_free_principal(d->context, in_creds.client);181if(ret)182return ret;183184ret = v5_convert(d->context, d->id, out_creds, uid,185(inst != NULL && inst[0] != '\0') ? inst : realm, kt);186krb5_free_creds(d->context, out_creds);187188return ret;189}190191static const char *192get_error(struct kafs_data *data, int error)193{194struct krb5_kafs_data *d = data->data;195return krb5_get_error_message(d->context, error);196}197198static void199free_error(struct kafs_data *data, const char *str)200{201struct krb5_kafs_data *d = data->data;202krb5_free_error_message(d->context, str);203}204205static krb5_error_code206afslog_uid_int(struct kafs_data *data, const char *cell, const char *rh,207uid_t uid, const char *homedir)208{209krb5_error_code ret;210struct kafs_token kt;211krb5_principal princ;212const char *trealm; /* ticket realm */213struct krb5_kafs_data *d = data->data;214215if (cell == 0 || cell[0] == 0)216return _kafs_afslog_all_local_cells (data, uid, homedir);217218ret = krb5_cc_get_principal (d->context, d->id, &princ);219if (ret)220return ret;221222trealm = krb5_principal_get_realm (d->context, princ);223224kt.ticket = NULL;225ret = _kafs_get_cred(data, cell, d->realm, trealm, uid, &kt);226krb5_free_principal (d->context, princ);227228if(ret == 0) {229ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);230free(kt.ticket);231}232return ret;233}234235static char *236get_realm(struct kafs_data *data, const char *host)237{238struct krb5_kafs_data *d = data->data;239krb5_realm *realms;240char *r;241if(krb5_get_host_realm(d->context, host, &realms))242return NULL;243r = strdup(realms[0]);244krb5_free_host_realm(d->context, realms);245return r;246}247248krb5_error_code249krb5_afslog_uid_home(krb5_context context,250krb5_ccache id,251const char *cell,252krb5_const_realm realm,253uid_t uid,254const char *homedir)255{256struct kafs_data kd;257struct krb5_kafs_data d;258krb5_error_code ret;259260kd.name = "krb5";261kd.afslog_uid = afslog_uid_int;262kd.get_cred = get_cred;263kd.get_realm = get_realm;264kd.get_error = get_error;265kd.free_error = free_error;266kd.data = &d;267if (context == NULL) {268ret = krb5_init_context(&d.context);269if (ret)270return ret;271} else272d.context = context;273if (id == NULL) {274ret = krb5_cc_default(d.context, &d.id);275if (ret)276goto out;277} else278d.id = id;279d.realm = realm;280ret = afslog_uid_int(&kd, cell, 0, uid, homedir);281if (id == NULL)282krb5_cc_close(context, d.id);283out:284if (context == NULL)285krb5_free_context(d.context);286return ret;287}288289krb5_error_code290krb5_afslog_uid(krb5_context context,291krb5_ccache id,292const char *cell,293krb5_const_realm realm,294uid_t uid)295{296return krb5_afslog_uid_home (context, id, cell, realm, uid, NULL);297}298299krb5_error_code300krb5_afslog(krb5_context context,301krb5_ccache id,302const char *cell,303krb5_const_realm realm)304{305return krb5_afslog_uid (context, id, cell, realm, getuid());306}307308krb5_error_code309krb5_afslog_home(krb5_context context,310krb5_ccache id,311const char *cell,312krb5_const_realm realm,313const char *homedir)314{315return krb5_afslog_uid_home (context, id, cell, realm, getuid(), homedir);316}317318/*319*320*/321322krb5_error_code323krb5_realm_of_cell(const char *cell, char **realm)324{325struct kafs_data kd;326327kd.name = "krb5";328kd.get_realm = get_realm;329kd.get_error = get_error;330kd.free_error = free_error;331return _kafs_realm_of_cell(&kd, cell, realm);332}333334/*335*336*/337338int339kafs_settoken5(krb5_context context, const char *cell, uid_t uid,340krb5_creds *cred)341{342struct kafs_token kt;343int ret;344345ret = v5_convert(context, NULL, cred, uid, cell, &kt);346if (ret)347return ret;348349ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);350351free(kt.ticket);352353return ret;354}355356357