convert_creds.c revision 55682
155682Smarkm/*
255682Smarkm * Copyright (c) 1997, 1999 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
3555682SmarkmRCSID("$Id: convert_creds.c,v 1.13 1999/12/02 17:05:08 joda Exp $");
3655682Smarkm
3755682Smarkmstatic krb5_error_code
3855682Smarkmcheck_ticket_flags(TicketFlags f)
3955682Smarkm{
4055682Smarkm    return 0; /* maybe add some more tests here? */
4155682Smarkm}
4255682Smarkm
4355682Smarkm/* include this here, to avoid dependencies on libkrb */
4455682Smarkm
4555682Smarkm#define		MAX_KTXT_LEN	1250
4655682Smarkm
4755682Smarkm#define 	ANAME_SZ	40
4855682Smarkm#define		REALM_SZ	40
4955682Smarkm#define		SNAME_SZ	40
5055682Smarkm#define		INST_SZ		40
5155682Smarkm
5255682Smarkmstruct ktext {
5355682Smarkm    unsigned int length;		/* Length of the text */
5455682Smarkm    unsigned char dat[MAX_KTXT_LEN];	/* The data itself */
5555682Smarkm    u_int32_t mbz;		/* zero to catch runaway strings */
5655682Smarkm};
5755682Smarkm
5855682Smarkmstruct credentials {
5955682Smarkm    char    service[ANAME_SZ];	/* Service name */
6055682Smarkm    char    instance[INST_SZ];	/* Instance */
6155682Smarkm    char    realm[REALM_SZ];	/* Auth domain */
6255682Smarkm    des_cblock session;		/* Session key */
6355682Smarkm    int     lifetime;		/* Lifetime */
6455682Smarkm    int     kvno;		/* Key version number */
6555682Smarkm    struct ktext ticket_st;	/* The ticket itself */
6655682Smarkm    int32_t    issue_date;	/* The issue time */
6755682Smarkm    char    pname[ANAME_SZ];	/* Principal's name */
6855682Smarkm    char    pinst[INST_SZ];	/* Principal's instance */
6955682Smarkm};
7055682Smarkm
7155682Smarkm
7255682Smarkm#define TKTLIFENUMFIXED 64
7355682Smarkm#define TKTLIFEMINFIXED 0x80
7455682Smarkm#define TKTLIFEMAXFIXED 0xBF
7555682Smarkm#define TKTLIFENOEXPIRE 0xFF
7655682Smarkm#define MAXTKTLIFETIME	(30*24*3600)	/* 30 days */
7755682Smarkm#ifndef NEVERDATE
7855682Smarkm#define NEVERDATE ((time_t)0x7fffffffL)
7955682Smarkm#endif
8055682Smarkm
8155682Smarkmstatic const int _tkt_lifetimes[TKTLIFENUMFIXED] = {
8255682Smarkm   38400,   41055,   43894,   46929,   50174,   53643,   57352,   61318,
8355682Smarkm   65558,   70091,   74937,   80119,   85658,   91581,   97914,  104684,
8455682Smarkm  111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
8555682Smarkm  191077,  204289,  218415,  233517,  249664,  266926,  285383,  305116,
8655682Smarkm  326213,  348769,  372885,  398668,  426234,  455705,  487215,  520904,
8755682Smarkm  556921,  595430,  636601,  680618,  727680,  777995,  831789,  889303,
8855682Smarkm  950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
8955682Smarkm 1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
9055682Smarkm};
9155682Smarkm
9255682Smarkmstatic int
9355682Smarkm_krb_time_to_life(time_t start, time_t end)
9455682Smarkm{
9555682Smarkm    int i;
9655682Smarkm    time_t life = end - start;
9755682Smarkm
9855682Smarkm    if (life > MAXTKTLIFETIME || life <= 0)
9955682Smarkm	return 0;
10055682Smarkm#if 0
10155682Smarkm    if (krb_no_long_lifetimes)
10255682Smarkm	return (life + 5*60 - 1)/(5*60);
10355682Smarkm#endif
10455682Smarkm
10555682Smarkm    if (end >= NEVERDATE)
10655682Smarkm	return TKTLIFENOEXPIRE;
10755682Smarkm    if (life < _tkt_lifetimes[0])
10855682Smarkm	return (life + 5*60 - 1)/(5*60);
10955682Smarkm    for (i=0; i<TKTLIFENUMFIXED; i++)
11055682Smarkm	if (life <= _tkt_lifetimes[i])
11155682Smarkm	    return i + TKTLIFEMINFIXED;
11255682Smarkm    return 0;
11355682Smarkm
11455682Smarkm}
11555682Smarkm
11655682Smarkm/* Convert the v5 credentials in `in_cred' to v4-dito in `v4creds'.
11755682Smarkm * This is done by sending them to the 524 function in the KDC.  If
11855682Smarkm * `in_cred' doesn't contain a DES session key, then a new one is
11955682Smarkm * gotten from the KDC and stored in the cred cache `ccache'.
12055682Smarkm */
12155682Smarkm
12255682Smarkmkrb5_error_code
12355682Smarkmkrb524_convert_creds_kdc(krb5_context context,
12455682Smarkm			 krb5_ccache ccache,
12555682Smarkm			 krb5_creds *in_cred,
12655682Smarkm			 struct credentials *v4creds)
12755682Smarkm{
12855682Smarkm    krb5_error_code ret;
12955682Smarkm    krb5_data reply;
13055682Smarkm    krb5_storage *sp;
13155682Smarkm    int32_t tmp;
13255682Smarkm    krb5_data ticket;
13355682Smarkm    char realm[REALM_SZ];
13455682Smarkm    krb5_creds *v5_creds = in_cred;
13555682Smarkm    krb5_keytype keytype;
13655682Smarkm
13755682Smarkm    ret = krb5_enctype_to_keytype (context, v5_creds->session.keytype,
13855682Smarkm				   &keytype);
13955682Smarkm    if (ret)
14055682Smarkm	return ret;
14155682Smarkm
14255682Smarkm    if (keytype != KEYTYPE_DES) {
14355682Smarkm	krb5_creds template;
14455682Smarkm
14555682Smarkm	memset (&template, 0, sizeof(template));
14655682Smarkm	template.session.keytype = KEYTYPE_DES;
14755682Smarkm	ret = krb5_copy_principal (context, in_cred->client, &template.client);
14855682Smarkm	if (ret) {
14955682Smarkm	    krb5_free_creds_contents (context, &template);
15055682Smarkm	    return ret;
15155682Smarkm	}
15255682Smarkm	ret = krb5_copy_principal (context, in_cred->server, &template.server);
15355682Smarkm	if (ret) {
15455682Smarkm	    krb5_free_creds_contents (context, &template);
15555682Smarkm	    return ret;
15655682Smarkm	}
15755682Smarkm
15855682Smarkm	ret = krb5_get_credentials (context, 0, ccache,
15955682Smarkm				    &template, &v5_creds);
16055682Smarkm	krb5_free_creds_contents (context, &template);
16155682Smarkm	if (ret)
16255682Smarkm	    return ret;
16355682Smarkm    }
16455682Smarkm
16555682Smarkm    ret = check_ticket_flags(v5_creds->flags.b);
16655682Smarkm    if(ret)
16755682Smarkm	goto out2;
16855682Smarkm
16955682Smarkm    ret = krb5_sendto_kdc (context,
17055682Smarkm			   &v5_creds->ticket,
17155682Smarkm			   krb5_princ_realm(context, v5_creds->server),
17255682Smarkm			   &reply);
17355682Smarkm    if (ret)
17455682Smarkm	goto out2;
17555682Smarkm    sp = krb5_storage_from_mem(reply.data, reply.length);
17655682Smarkm    if(sp == NULL) {
17755682Smarkm	ret = ENOMEM;
17855682Smarkm	goto out2;
17955682Smarkm    }
18055682Smarkm    krb5_ret_int32(sp, &tmp);
18155682Smarkm    ret = tmp;
18255682Smarkm    if(ret == 0) {
18355682Smarkm	memset(v4creds, 0, sizeof(*v4creds));
18455682Smarkm	ret = krb5_ret_int32(sp, &tmp);
18555682Smarkm	if(ret) goto out;
18655682Smarkm	v4creds->kvno = tmp;
18755682Smarkm	ret = krb5_ret_data(sp, &ticket);
18855682Smarkm	if(ret) goto out;
18955682Smarkm	v4creds->ticket_st.length = ticket.length;
19055682Smarkm	memcpy(v4creds->ticket_st.dat, ticket.data, ticket.length);
19155682Smarkm	krb5_data_free(&ticket);
19255682Smarkm	ret = krb5_524_conv_principal(context,
19355682Smarkm				      v5_creds->server,
19455682Smarkm				      v4creds->service,
19555682Smarkm				      v4creds->instance,
19655682Smarkm				      v4creds->realm);
19755682Smarkm	if(ret) goto out;
19855682Smarkm	v4creds->issue_date = v5_creds->times.authtime;
19955682Smarkm	v4creds->lifetime = _krb_time_to_life(v4creds->issue_date,
20055682Smarkm					      v5_creds->times.endtime);
20155682Smarkm	ret = krb5_524_conv_principal(context, v5_creds->client,
20255682Smarkm				      v4creds->pname,
20355682Smarkm				      v4creds->pinst,
20455682Smarkm				      realm);
20555682Smarkm	if(ret) goto out;
20655682Smarkm	memcpy(v4creds->session, v5_creds->session.keyvalue.data, 8);
20755682Smarkm    }
20855682Smarkmout:
20955682Smarkm    krb5_storage_free(sp);
21055682Smarkm    krb5_data_free(&reply);
21155682Smarkmout2:
21255682Smarkm    if (v5_creds != in_cred)
21355682Smarkm	krb5_free_creds (context, v5_creds);
21455682Smarkm    return ret;
21555682Smarkm}
216