Beispiel #1
0
krb5_error_code KRB5_CALLCONV
krb5_rd_priv(krb5_context context, krb5_auth_context auth_context,
	     const krb5_data *inbuf, krb5_data *outbuf,
	     krb5_replay_data *outdata)
{
    krb5_error_code 	  retval;
    krb5_keyblock       * keyblock;
    krb5_replay_data	  replaydata;

    /* Get keyblock */
    if ((keyblock = auth_context->recv_subkey) == NULL)
	keyblock = auth_context->keyblock;

    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
      (outdata == NULL))
	/* Need a better error */
	return KRB5_RC_REQUIRED;

    if (!auth_context->remote_addr)
	return KRB5_REMOTE_ADDR_REQUIRED;

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
      (auth_context->rcache == NULL))
	return KRB5_RC_REQUIRED;

{
    krb5_address * premote_fulladdr;
    krb5_address * plocal_fulladdr = NULL;
    krb5_address remote_fulladdr;
    krb5_address local_fulladdr;
    CLEANUP_INIT(2);

    if (auth_context->local_addr) {
    	if (auth_context->local_port) {
            if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
                                 	      auth_context->local_port, 
					      &local_fulladdr))){
                CLEANUP_PUSH(local_fulladdr.contents, free);
	        plocal_fulladdr = &local_fulladdr;
            } else {
	        return retval;
            }
	} else {
            plocal_fulladdr = auth_context->local_addr;
        }
    }

    if (auth_context->remote_port) {
	if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
					  auth_context->remote_port, 
					  &remote_fulladdr))){
	    CLEANUP_PUSH(remote_fulladdr.contents, free);
	    premote_fulladdr = &remote_fulladdr;
	} else {
	    CLEANUP_DONE();
	    return retval;
	}
    } else {
	premote_fulladdr = auth_context->remote_addr;
    }

    memset(&replaydata, 0, sizeof(replaydata));
    if ((retval = krb5_rd_priv_basic(context, inbuf, keyblock,
				     plocal_fulladdr,
				     premote_fulladdr,
				     auth_context->i_vector,
				     &replaydata, outbuf))) {
	CLEANUP_DONE();
	return retval;
    }

    CLEANUP_DONE();
}

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_donot_replay replay;

	if ((retval = krb5int_check_clockskew(context, replaydata.timestamp)))
	    goto error;

	if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, 
					   "_priv", &replay.client)))
	    goto error;

	replay.server = "";		/* XXX */
	replay.msghash = NULL;
	replay.cusec = replaydata.usec;
	replay.ctime = replaydata.timestamp;
	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
	    free(replay.client);
	    goto error;
	}
	free(replay.client);
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
	if (!krb5int_auth_con_chkseqnum(context, auth_context,
					replaydata.seq)) {
	    retval =  KRB5KRB_AP_ERR_BADORDER;
	    goto error;
	}
	auth_context->remote_seq_number++;
    }

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
      (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
	outdata->timestamp = replaydata.timestamp;
	outdata->usec = replaydata.usec;
	outdata->seq = replaydata.seq;
    }
	
    /* everything is ok - return data to the user */
    return 0;

error:;
    free(outbuf->data);
    outbuf->length = 0;
    outbuf->data = NULL;

    return retval;
}
Beispiel #2
0
krb5_error_code KRB5_CALLCONV
krb5_mk_priv(krb5_context context, krb5_auth_context auth_context,
             const krb5_data *userdata, krb5_data *outbuf,
             krb5_replay_data *outdata)
{
    krb5_error_code       retval;
    krb5_key              key;
    krb5_replay_data      replaydata;
    krb5_data             buf = empty_data();

    *outbuf = empty_data();

    /* Clear replaydata block */
    memset(&replaydata, 0, sizeof(krb5_replay_data));

    /* Get keyblock */
    if ((key = auth_context->send_subkey) == NULL)
        key = auth_context->key;

    /* Get replay info */
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
        (auth_context->rcache == NULL))
        return KRB5_RC_REQUIRED;

    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
         (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
        (outdata == NULL))
        /* Need a better error */
        return KRB5_RC_REQUIRED;

    if (!auth_context->local_addr)
        return KRB5_LOCAL_ADDR_REQUIRED;

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
        if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
                                        &replaydata.usec)))
            return retval;
        if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
            outdata->timestamp = replaydata.timestamp;
            outdata->usec = replaydata.usec;
        }
    }
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
        replaydata.seq = auth_context->local_seq_number++;
        if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
            outdata->seq = replaydata.seq;
    }

    {
        krb5_address * premote_fulladdr = NULL;
        krb5_address * plocal_fulladdr;
        krb5_address remote_fulladdr;
        krb5_address local_fulladdr;
        CLEANUP_INIT(2);

        if (auth_context->local_port) {
            if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
                                              auth_context->local_port,
                                              &local_fulladdr))) {
                CLEANUP_PUSH(local_fulladdr.contents, free);
                plocal_fulladdr = &local_fulladdr;
            } else {
                goto error;
            }
        } else {
            plocal_fulladdr = auth_context->local_addr;
        }

        if (auth_context->remote_addr) {
            if (auth_context->remote_port) {
                if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
                                                  auth_context->remote_port,
                                                  &remote_fulladdr))){
                    CLEANUP_PUSH(remote_fulladdr.contents, free);
                    premote_fulladdr = &remote_fulladdr;
                } else {
                    CLEANUP_DONE();
                    goto error;
                }
            } else {
                premote_fulladdr = auth_context->remote_addr;
            }
        }

        if ((retval = mk_priv_basic(context, userdata, key, &replaydata,
                                    plocal_fulladdr, premote_fulladdr,
                                    &auth_context->cstate, &buf))) {
            CLEANUP_DONE();
            goto error;
        }

        CLEANUP_DONE();
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
        krb5_donot_replay replay;

        if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
                                           "_priv", &replay.client)))
            goto error;

        replay.server = "";             /* XXX */
        replay.msghash = NULL;
        replay.cusec = replaydata.usec;
        replay.ctime = replaydata.timestamp;
        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
            /* should we really error out here? XXX */
            free(replay.client);
            goto error;
        }
        free(replay.client);
    }

    *outbuf = buf;
    return 0;

error:
    krb5_free_data_contents(context, &buf);
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
        auth_context->local_seq_number--;

    return retval;
}
Beispiel #3
0
/* XXX - check for cleanup */
krb5_error_code
setup_auth_context(krb5_context context,
		   krb5_auth_context auth_context,
		   struct sockaddr_in *localaddr,
		   struct sockaddr_in *remoteaddr,
		   char *uniq)
{
    krb5_address  	laddr, raddr, *portlocal_addr;
    krb5_rcache 	rcache;
    krb5_data		rcache_name;
    char       		*outaddr;
    krb5_error_code	retval;


#ifndef HEIMDAL
/* Setting ports isn't compatible with Heimdal, if this code
   is enabled, it's not possible to have an interoperable setup */
#if 0
    laddr.addrtype = ADDRTYPE_IPPORT;
    laddr.length = sizeof(localaddr->sin_port);
    laddr.contents = (krb5_octet *)&(localaddr->sin_port);

    raddr.addrtype = ADDRTYPE_IPPORT;
    raddr.length = sizeof(remoteaddr->sin_port);
    raddr.contents = (krb5_octet *)&(remoteaddr->sin_port);
    if (retval = krb5_auth_con_setports(context, auth_context,
					 &laddr, &raddr)) {
	sprintf(auth_con_error, "%s while setting auth_con ports\n",
		error_message(retval));
	return retval;
    }
#endif
#endif

#ifdef HEIMDAL
    laddr.addr_type = KRB5_ADDRESS_INET;
    laddr.address.length = sizeof(localaddr->sin_addr);
    laddr.address.data = (void *)&(localaddr->sin_addr);

    raddr.addr_type = KRB5_ADDRESS_INET;
    raddr.address.length = sizeof(remoteaddr->sin_addr);
    raddr.address.data = (void *)&(remoteaddr->sin_addr);
#else
    laddr.addrtype = ADDRTYPE_INET;
    laddr.length = sizeof(localaddr->sin_addr);
    laddr.contents = (krb5_octet *)&(localaddr->sin_addr);

    raddr.addrtype = ADDRTYPE_INET;
    raddr.length = sizeof(remoteaddr->sin_addr);
    raddr.contents = (krb5_octet *)&(remoteaddr->sin_addr);
#endif

    if (retval = krb5_auth_con_setaddrs(context, auth_context,
					 &laddr, &raddr)) {
	sprintf(auth_con_error, "%s while setting auth_con addresses\n",
		error_message(retval));
	return retval;
    }


#ifdef HEIMDAL
#else
    /* Set up replay cache */ 
    if ((retval = krb5_gen_portaddr(context,
				    &laddr,
				    (krb5_pointer) &(localaddr->sin_port),
				    &portlocal_addr))) {
	sprintf(auth_con_error, "%s while generating port address",
		error_message(retval));
	return retval;
    }
    
    if ((retval = krb5_gen_replay_name(context, portlocal_addr,
				       uniq, &outaddr))) {
	sprintf(auth_con_error, "%s while generating replay cache name",
		error_message(retval));
	return retval;
    }

    rcache_name.length = strlen(outaddr);
    rcache_name.data = outaddr;

    if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) {
	sprintf(auth_con_error, "%s while getting server rcache",
		error_message(retval));
	return retval;
    }

    if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) {
	sprintf(auth_con_error, "%s setting rcache",
		error_message(retval));
	return retval;
    }
#endif
	
    return retval;
}
Beispiel #4
0
krb5_error_code KRB5_CALLCONV
krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
             const krb5_data *userdata, krb5_data *outbuf,
             krb5_replay_data *outdata)
{
    krb5_error_code       retval;
    krb5_key              key;
    krb5_replay_data      replaydata;

    /* Clear replaydata block */
    memset(&replaydata, 0, sizeof(krb5_replay_data));

    /* Get key */
    if ((key = auth_context->send_subkey) == NULL)
        key = auth_context->key;

    /* Get replay info */
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
        (auth_context->rcache == NULL))
        return KRB5_RC_REQUIRED;

    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
         (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
        (outdata == NULL))
        /* Need a better error */
        return KRB5_RC_REQUIRED;

    if (!auth_context->local_addr)
        return KRB5_LOCAL_ADDR_REQUIRED;

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
        if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
                                        &replaydata.usec)))
            return retval;
        if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
            outdata->timestamp = replaydata.timestamp;
            outdata->usec = replaydata.usec;
        }
    }
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
        replaydata.seq = auth_context->local_seq_number++;
        if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
            outdata->seq = replaydata.seq;
    }

    {
        krb5_address * premote_fulladdr = NULL;
        krb5_address * plocal_fulladdr;
        krb5_address remote_fulladdr;
        krb5_address local_fulladdr;
        krb5_cksumtype sumtype;

        CLEANUP_INIT(2);

        if (auth_context->local_port) {
            if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
                                              auth_context->local_port,
                                              &local_fulladdr))){
                CLEANUP_PUSH(local_fulladdr.contents, free);
                plocal_fulladdr = &local_fulladdr;
            } else {
                goto error;
            }
        } else {
            plocal_fulladdr = auth_context->local_addr;
        }

        if (auth_context->remote_addr) {
            if (auth_context->remote_port) {
                if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
                                                  auth_context->remote_port,
                                                  &remote_fulladdr))){
                    CLEANUP_PUSH(remote_fulladdr.contents, free);
                    premote_fulladdr = &remote_fulladdr;
                } else {
                    CLEANUP_DONE();
                    goto error;
                }
            } else {
                premote_fulladdr = auth_context->remote_addr;
            }
        }

        {
            krb5_enctype enctype = krb5_k_key_enctype(context, key);
            unsigned int nsumtypes;
            unsigned int i;
            krb5_cksumtype *sumtypes;
            retval = krb5_c_keyed_checksum_types (context, enctype,
                                                  &nsumtypes, &sumtypes);
            if (retval) {
                CLEANUP_DONE ();
                goto error;
            }
            if (nsumtypes == 0) {
                retval = KRB5_BAD_ENCTYPE;
                krb5_free_cksumtypes (context, sumtypes);
                CLEANUP_DONE ();
                goto error;
            }
            for (i = 0; i < nsumtypes; i++)
                if (auth_context->safe_cksumtype == sumtypes[i])
                    break;
            krb5_free_cksumtypes (context, sumtypes);
            if (i < nsumtypes)
                sumtype = auth_context->safe_cksumtype;
            else {
                switch (enctype) {
                case ENCTYPE_DES_CBC_MD4:
                    sumtype = CKSUMTYPE_RSA_MD4_DES;
                    break;
                case ENCTYPE_DES_CBC_MD5:
                case ENCTYPE_DES_CBC_CRC:
                    sumtype = CKSUMTYPE_RSA_MD5_DES;
                    break;
                default:
                    retval = krb5int_c_mandatory_cksumtype(context, enctype,
                                                           &sumtype);
                    if (retval) {
                        CLEANUP_DONE();
                        goto error;
                    }
                    break;
                }
            }
        }
        if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata,
                                         plocal_fulladdr, premote_fulladdr,
                                         sumtype, outbuf))) {
            CLEANUP_DONE();
            goto error;
        }

        CLEANUP_DONE();
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
        krb5_donot_replay replay;

        if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
                                           "_safe", &replay.client))) {
            free(outbuf);
            goto error;
        }

        replay.server = "";             /* XXX */
        replay.msghash = NULL;
        replay.cusec = replaydata.usec;
        replay.ctime = replaydata.timestamp;
        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
            /* should we really error out here? XXX */
            free(outbuf);
            goto error;
        }
        free(replay.client);
    }

    return 0;

error:
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
        auth_context->local_seq_number--;

    return retval;
}
Beispiel #5
0
krb5_error_code KRB5_CALLCONV
krb5_rd_safe(krb5_context context, krb5_auth_context auth_context,
             const krb5_data *inbuf, krb5_data *outbuf,
             krb5_replay_data *outdata)
{
    krb5_error_code       retval;
    krb5_key              key;
    krb5_replay_data      replaydata;

    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
         (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
        (outdata == NULL))
        /* Need a better error */
        return KRB5_RC_REQUIRED;

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
        (auth_context->remote_addr == NULL))
        return KRB5_REMOTE_ADDR_REQUIRED;

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
        (auth_context->rcache == NULL))
        return KRB5_RC_REQUIRED;

    /* Get key */
    if ((key = auth_context->recv_subkey) == NULL)
        key = auth_context->key;

    memset(&replaydata, 0, sizeof(replaydata));
    retval = rd_safe_basic(context, auth_context, inbuf, key, &replaydata,
                           outbuf);
    if (retval)
        return retval;

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
        krb5_donot_replay replay;

        if ((retval = krb5_check_clockskew(context, replaydata.timestamp)))
            goto error;

        if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
                                           "_safe", &replay.client)))
            goto error;

        replay.server = "";             /* XXX */
        replay.msghash = NULL;
        replay.cusec = replaydata.usec;
        replay.ctime = replaydata.timestamp;
        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
            free(replay.client);
            goto error;
        }
        free(replay.client);
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
        if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) {
            retval =  KRB5KRB_AP_ERR_BADORDER;
            goto error;
        }
        auth_context->remote_seq_number++;
    }

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
        outdata->timestamp = replaydata.timestamp;
        outdata->usec = replaydata.usec;
        outdata->seq = replaydata.seq;
    }

    /* everything is ok - return data to the user */
    return 0;

error:
    free(outbuf->data);
    return retval;

}
Beispiel #6
0
/*
 * This functions takes as input an array of krb5_credentials, and
 * outputs an encoded KRB_CRED message suitable for krb5_rd_cred
 */
krb5_error_code KRB5_CALLCONV
krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context,
              krb5_creds **ppcreds, krb5_data **ppdata,
              krb5_replay_data *outdata)
{
    krb5_address * premote_fulladdr = NULL;
    krb5_address * plocal_fulladdr = NULL;
    krb5_address remote_fulladdr;
    krb5_address local_fulladdr;
    krb5_error_code     retval;
    krb5_key            key;
    krb5_replay_data    replaydata;
    krb5_cred            * pcred;
    krb5_int32          ncred;
    krb5_boolean increased_sequence = FALSE;

    local_fulladdr.contents = 0;
    remote_fulladdr.contents = 0;
    memset(&replaydata, 0, sizeof(krb5_replay_data));

    if (ppcreds == NULL)
        return KRB5KRB_AP_ERR_BADADDR;

    /*
     * Allocate memory for a NULL terminated list of tickets.
     */
    for (ncred = 0; ppcreds[ncred]; ncred++)
        ;

    if ((pcred = (krb5_cred *)calloc(1, sizeof(krb5_cred))) == NULL)
        return ENOMEM;

    if ((pcred->tickets
         = (krb5_ticket **)calloc((size_t)ncred+1,
                                  sizeof(krb5_ticket *))) == NULL) {
        retval = ENOMEM;
        goto error;
    }

    /* Get keyblock */
    if ((key = auth_context->send_subkey) == NULL)
        key = auth_context->key;

    /* Get replay info */
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
        (auth_context->rcache == NULL)) {
        retval = KRB5_RC_REQUIRED;
        goto error;
    }

    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
         (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
        && (outdata == NULL)) {
        /* Need a better error */
        retval = KRB5_RC_REQUIRED;
        goto error;
    }

    if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
                                    &replaydata.usec)))
        goto error;
    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
        outdata->timestamp = replaydata.timestamp;
        outdata->usec = replaydata.usec;
    }
    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
        replaydata.seq = auth_context->local_seq_number++;
        increased_sequence = TRUE;
        if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
            outdata->seq = replaydata.seq;
    }

    if (auth_context->local_addr) {
        if (auth_context->local_port) {
            if ((retval = krb5_make_fulladdr(context, auth_context->local_addr,
                                             auth_context->local_port,
                                             &local_fulladdr)))
                goto error;
            plocal_fulladdr = &local_fulladdr;
        } else {
            plocal_fulladdr = auth_context->local_addr;
        }
    }

    if (auth_context->remote_addr) {
        if (auth_context->remote_port) {
            if ((retval = krb5_make_fulladdr(context,auth_context->remote_addr,
                                             auth_context->remote_port,
                                             &remote_fulladdr)))
                goto error;
            premote_fulladdr = &remote_fulladdr;
        } else {
            premote_fulladdr = auth_context->remote_addr;
        }
    }

    /* Setup creds structure */
    if ((retval = krb5_mk_ncred_basic(context, ppcreds, ncred, key,
                                      &replaydata, plocal_fulladdr,
                                      premote_fulladdr, pcred))) {
        goto error;
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
        krb5_donot_replay replay;

        if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
                                           "_forw", &replay.client)))
            goto error;

        replay.server = "";             /* XXX */
        replay.msghash = NULL;
        replay.cusec = replaydata.usec;
        replay.ctime = replaydata.timestamp;
        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
            /* should we really error out here? XXX */
            free(replay.client);
            goto error;
        }
        free(replay.client);
    }

    /* Encode creds structure */
    retval = encode_krb5_cred(pcred, ppdata);

error:
    free(local_fulladdr.contents);
    free(remote_fulladdr.contents);
    krb5_free_cred(context, pcred);

    if (retval) {
        if (increased_sequence)
            auth_context->local_seq_number--;
    }
    return retval;
}
Beispiel #7
0
/*
 * This functions takes as input an KRB_CRED message, validates it, and
 * outputs the array of the forwarded credentials and replay cache information
 */
krb5_error_code KRB5_CALLCONV
krb5_rd_cred(krb5_context context, krb5_auth_context auth_context,
             krb5_data *pcreddata, krb5_creds ***pppcreds,
             krb5_replay_data *outdata)
{
    krb5_error_code       retval = 0;
    krb5_replay_data      replaydata;

    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
         (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
        (outdata == NULL))
        /* Need a better error */
        return KRB5_RC_REQUIRED;

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
        (auth_context->rcache == NULL))
        return KRB5_RC_REQUIRED;

    /*
     * If decrypting with the subsession key fails, perhaps the
     * credentials are stored in the session key so try decrypting with that.
     */
    if (auth_context->recv_subkey == NULL ||
        (retval = krb5_rd_cred_basic(context, pcreddata,
                                     auth_context->recv_subkey,
                                     &replaydata, pppcreds))) {
        retval = krb5_rd_cred_basic(context, pcreddata,
                                    auth_context->key,
                                    &replaydata, pppcreds);
        if (retval)
            return retval;
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
        krb5_donot_replay replay;

        if ((retval = krb5_check_clockskew(context, replaydata.timestamp)))
            goto error;

        if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
                                           "_forw", &replay.client)))
            goto error;

        replay.server = "";             /* XXX */
        replay.msghash = NULL;
        replay.cusec = replaydata.usec;
        replay.ctime = replaydata.timestamp;
        if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
            free(replay.client);
            goto error;
        }
        free(replay.client);
    }

    if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
        if (auth_context->remote_seq_number != replaydata.seq) {
            retval =  KRB5KRB_AP_ERR_BADORDER;
            goto error;
        }
        auth_context->remote_seq_number++;
    }

    if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
        (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
        outdata->timestamp = replaydata.timestamp;
        outdata->usec = replaydata.usec;
        outdata->seq = replaydata.seq;
    }

error:;
    if (retval) {
        krb5_free_tgt_creds(context, *pppcreds);
        *pppcreds = NULL;
    }
    return retval;
}