Пример #1
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;
}
Пример #2
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;
}
Пример #3
0
/*
 * Verify the sender and receiver addresses from a KRB-SAFE or KRB-PRIV message
 * against the auth context.  msg_r_addr may be NULL, but msg_s_addr must not
 * be.  The auth context's remote addr must be set.
 */
krb5_error_code
k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac,
                        krb5_address *msg_s_addr, krb5_address *msg_r_addr)
{
    krb5_error_code ret = 0;
    krb5_address **our_addrs = NULL;
    const krb5_address *local_addr, *remote_addr;
    krb5_address local_fulladdr, remote_fulladdr;

    local_fulladdr.contents = remote_fulladdr.contents = NULL;

    /* Determine the remote comparison address. */
    if (ac->remote_port != NULL) {
        ret = krb5_make_fulladdr(context, ac->remote_addr, ac->remote_port,
                                 &remote_fulladdr);
        if (ret)
            goto cleanup;
        remote_addr = &remote_fulladdr;
    } else
        remote_addr = ac->remote_addr;

    /* Determine the local comparison address (possibly NULL). */
    if (ac->local_addr != NULL) {
        if (ac->local_port != NULL) {
            ret = krb5_make_fulladdr(context, ac->local_addr, ac->local_port,
                                     &local_fulladdr);
            if (ret)
                goto cleanup;
            local_addr = &local_fulladdr;
        } else
            local_addr = ac->local_addr;
    } else
        local_addr = NULL;

    /* Check the remote address against the message's sender address. */
    if (!krb5_address_compare(context, remote_addr, msg_s_addr)) {
        ret = KRB5KRB_AP_ERR_BADADDR;
        goto cleanup;
    }

    /* Receiver address is optional; only check it if supplied. */
    if (msg_r_addr == NULL)
        goto cleanup;

    /* Check the message's receiver address against the local address, or
     * against all local addresses if no specific local address is set. */
    if (local_addr != NULL) {
        if (!krb5_address_compare(context, local_addr, msg_r_addr)) {
            ret = KRB5KRB_AP_ERR_BADADDR;
            goto cleanup;
        }
    } else {
        ret = krb5_os_localaddr(context, &our_addrs);
        if (ret)
            goto cleanup;

        if (!krb5_address_search(context, msg_r_addr, our_addrs)) {
            ret = KRB5KRB_AP_ERR_BADADDR;
            goto cleanup;
        }
    }

cleanup:
    free(local_fulladdr.contents);
    free(remote_fulladdr.contents);
    krb5_free_addresses(context, our_addrs);
    return ret;
}
Пример #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;
}
Пример #5
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;
}