📄 get_in_tkt.c
字号:
/* * Copyright (c) 1997 - 2002 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "krb5_locl.h"RCSID("$Id: get_in_tkt.c 20226 2007-02-16 03:31:50Z lha $");krb5_error_code KRB5_LIB_FUNCTIONkrb5_init_etype (krb5_context context, unsigned *len, krb5_enctype **val, const krb5_enctype *etypes){ int i; krb5_error_code ret; krb5_enctype *tmp = NULL; ret = 0; if (etypes == NULL) { ret = krb5_get_default_in_tkt_etypes(context, &tmp); if (ret) return ret; etypes = tmp; } for (i = 0; etypes[i]; ++i) ; *len = i; *val = malloc(i * sizeof(**val)); if (i != 0 && *val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto cleanup; } memmove (*val, etypes, i * sizeof(*tmp));cleanup: if (tmp != NULL) free (tmp); return ret;}static krb5_error_codedecrypt_tkt (krb5_context context, krb5_keyblock *key, krb5_key_usage usage, krb5_const_pointer decrypt_arg, krb5_kdc_rep *dec_rep){ krb5_error_code ret; krb5_data data; size_t size; krb5_crypto crypto; ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) return ret; ret = krb5_decrypt_EncryptedData (context, crypto, usage, &dec_rep->kdc_rep.enc_part, &data); krb5_crypto_destroy(context, crypto); if (ret) return ret; ret = krb5_decode_EncASRepPart(context, data.data, data.length, &dec_rep->enc_part, &size); if (ret) ret = krb5_decode_EncTGSRepPart(context, data.data, data.length, &dec_rep->enc_part, &size); krb5_data_free (&data); if (ret) return ret; return 0;}int_krb5_extract_ticket(krb5_context context, krb5_kdc_rep *rep, krb5_creds *creds, krb5_keyblock *key, krb5_const_pointer keyseed, krb5_key_usage key_usage, krb5_addresses *addrs, unsigned nonce, unsigned flags, krb5_decrypt_proc decrypt_proc, krb5_const_pointer decryptarg){ krb5_error_code ret; krb5_principal tmp_principal; int tmp; size_t len; time_t tmp_time; krb5_timestamp sec_now;/* * HACK: * this is really a ugly hack, to support using the Netbios Domain Name * as realm against windows KDC's, they always return the full realm * based on the DNS Name. */flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); if (ret) goto out; /* compare client */ if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0){ tmp = krb5_principal_compare (context, tmp_principal, creds->client); if (!tmp) { krb5_free_principal (context, tmp_principal); krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_MODIFIED; goto out; } } krb5_free_principal (context, creds->client); creds->client = tmp_principal; /* extract ticket */ ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, &rep->kdc_rep.ticket, &len, ret); if(ret) goto out; if (creds->ticket.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); creds->second_ticket.length = 0; creds->second_ticket.data = NULL; /* compare server */ ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); if (ret) goto out; if(flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH){ krb5_free_principal(context, creds->server); creds->server = tmp_principal; tmp_principal = NULL; } else { tmp = krb5_principal_compare (context, tmp_principal, creds->server); krb5_free_principal (context, tmp_principal); if (!tmp) { ret = KRB5KRB_AP_ERR_MODIFIED; krb5_clear_error_string (context); goto out; } } /* decrypt */ if (decrypt_proc == NULL) decrypt_proc = decrypt_tkt; ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); if (ret) goto out; /* verify names */ if(flags & EXTRACT_TICKET_MATCH_REALM){ const char *srealm = krb5_principal_get_realm(context, creds->server); const char *crealm = krb5_principal_get_realm(context, creds->client); if (strcmp(rep->enc_part.srealm, srealm) != 0 || strcmp(rep->enc_part.srealm, crealm) != 0) { ret = KRB5KRB_AP_ERR_MODIFIED; krb5_clear_error_string(context); goto out; } } /* compare nonces */ if (nonce != rep->enc_part.nonce) { ret = KRB5KRB_AP_ERR_MODIFIED; krb5_set_error_string(context, "malloc: out of memory"); goto out; } /* set kdc-offset */ krb5_timeofday (context, &sec_now); if (rep->enc_part.flags.initial && context->kdc_sec_offset == 0 && krb5_config_get_bool (context, NULL, "libdefaults", "kdc_timesync", NULL)) { context->kdc_sec_offset = rep->enc_part.authtime - sec_now; krb5_timeofday (context, &sec_now); } /* check all times */ if (rep->enc_part.starttime) { tmp_time = *rep->enc_part.starttime; } else tmp_time = rep->enc_part.authtime; if (creds->times.starttime == 0 && abs(tmp_time - sec_now) > context->max_skew) { ret = KRB5KRB_AP_ERR_SKEW; krb5_set_error_string (context, "time skew (%d) larger than max (%d)", abs(tmp_time - sec_now), (int)context->max_skew); goto out; } if (creds->times.starttime != 0 && tmp_time != creds->times.starttime) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_MODIFIED; goto out; } creds->times.starttime = tmp_time; if (rep->enc_part.renew_till) { tmp_time = *rep->enc_part.renew_till; } else tmp_time = 0; if (creds->times.renew_till != 0 && tmp_time > creds->times.renew_till) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_MODIFIED; goto out; } creds->times.renew_till = tmp_time; creds->times.authtime = rep->enc_part.authtime; if (creds->times.endtime != 0 && rep->enc_part.endtime > creds->times.endtime) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_MODIFIED; goto out; } creds->times.endtime = rep->enc_part.endtime; if(rep->enc_part.caddr) krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses); else if(addrs) krb5_copy_addresses (context, addrs, &creds->addresses); else { creds->addresses.len = 0; creds->addresses.val = NULL; } creds->flags.b = rep->enc_part.flags; creds->authdata.len = 0; creds->authdata.val = NULL; creds->session.keyvalue.length = 0; creds->session.keyvalue.data = NULL; creds->session.keytype = rep->enc_part.key.keytype; ret = krb5_data_copy (&creds->session.keyvalue, rep->enc_part.key.keyvalue.data, rep->enc_part.key.keyvalue.length);out: memset (rep->enc_part.key.keyvalue.data, 0, rep->enc_part.key.keyvalue.length); return ret;}static krb5_error_codemake_pa_enc_timestamp(krb5_context context, PA_DATA *pa, krb5_enctype etype, krb5_keyblock *key){ PA_ENC_TS_ENC p; unsigned char *buf; size_t buf_size; size_t len; EncryptedData encdata; krb5_error_code ret; int32_t usec; int usec2; krb5_crypto crypto; krb5_us_timeofday (context, &p.patimestamp, &usec); usec2 = usec; p.pausec = &usec2; ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret); if (ret) return ret; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) { free(buf); return ret; } ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_PA_ENC_TIMESTAMP, buf, len, 0, &encdata); free(buf); krb5_crypto_destroy(context, crypto); if (ret) return ret; ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret); free_EncryptedData(&encdata); if (ret) return ret; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; pa->padata_value.length = len; pa->padata_value.data = buf; return 0;}static krb5_error_codeadd_padata(krb5_context context, METHOD_DATA *md, krb5_principal client, krb5_key_proc key_proc, krb5_const_pointer keyseed, krb5_enctype *enctypes, unsigned netypes, krb5_salt *salt){ krb5_error_code ret; PA_DATA *pa2; krb5_salt salt2; krb5_enctype *ep; int i; if(salt == NULL) { /* default to standard salt */ ret = krb5_get_pw_salt (context, client, &salt2); salt = &salt2; } if (!enctypes) { enctypes = context->etypes; netypes = 0; for (ep = enctypes; *ep != ETYPE_NULL; ep++) netypes++; } pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val)); if (pa2 == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } md->val = pa2; for (i = 0; i < netypes; ++i) { krb5_keyblock *key; ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key); if (ret) continue; ret = make_pa_enc_timestamp (context, &md->val[md->len], enctypes[i], key); krb5_free_keyblock (context, key); if (ret) return ret; ++md->len; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -