Esempio n. 1
0
static krb5_error_code 
krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
				    krb5_ccache ccache, krb5_creds *in_creds,
				    krb5_creds **out_creds, int which)
{
    krb5_error_code retval;
    krb5_principal tmp;
    krb5_creds **tgts = 0;

    switch(which) {
    case INT_GC_VALIDATE:
	    retval = krb5_get_cred_from_kdc_validate(context, ccache, 
					     in_creds, out_creds, &tgts);
	    break;
    case INT_GC_RENEW:
	    retval = krb5_get_cred_from_kdc_renew(context, ccache, 
					     in_creds, out_creds, &tgts);
	    break;
    default:
	    /* Should never happen */
	    retval = 255;
	    break;
    }
    if (retval) return retval;
    if (tgts) krb5_free_tgt_creds(context, tgts);

    retval = krb5_cc_get_principal(context, ccache, &tmp);
    if (retval) return retval;
    
    retval = krb5_cc_initialize(context, ccache, tmp);
    if (retval) return retval;
    
    retval = krb5_cc_store_cred(context, ccache, *out_creds);
    return retval;
}
Esempio n. 2
0
int
krb_renew_tgts(
lList *joblist 
) {
   krb5_error_code rc;
   static u_long32 next_time = 0;
   u_long32 now = sge_get_gmt();
   lListElem *job;
   krb5_context context = krb_context();
   krb5_timestamp time_now;
   krb_global_data_t *gsd = krb_gsd();

   DENTER(TOP_LAYER, "krb_renew_tgts");


   if ((now = sge_get_gmt())<next_time) {
      DEXIT;
      return 0;
   }

   if ((rc = krb5_timeofday(context, &time_now))) {
      ERROR((SGE_EVENT, MSG_KRB_KRB5TIMEOFDAYFAILEDX_S ,
	     error_message(rc)));
      DEXIT;
      return -1;
   }

   /* renew job TGT's */

   for_each(job, joblist) {

      krb5_error_code rc;
      krb5_creds ** tgt_creds = NULL;
      krb5_data tgtbuf;
      const char *tgtstr = NULL;

      tgtbuf.length = 0;

      /* get TGT out of job entry */

      if ((tgtstr = lGetString(job, JB_tgt))) {

         tgtbuf.data = krb_str2bin(tgtstr, NULL, &tgtbuf.length);

         if (tgtbuf.length) {

            /* decrypt the TGT using the daemon key */

            if ((rc = krb_decrypt_tgt_creds(&tgtbuf, &tgt_creds))) {

               ERROR((SGE_EVENT, MSG_KRB_COULDNOTDECRYPTTGTFORJOBXY_DS,
                      sge_u32c(lGetUlong(job, JB_job_number)),
                      error_message(rc)));

            }

	    if (rc == 0 && tgt_creds) {

               krb5_creds *tgt = *tgt_creds;

	       /*
		* If TGT is renewable and TGT expiration time is not past
		* and is within the SGE renewal threshold and the TGT
		* renewal period is not past, then renew the TGT
		*/

	       if (tgt->ticket_flags & KDC_OPT_RENEWABLE &&
		   tgt->times.endtime > time_now &&
		   tgt->times.renew_till > time_now &&
		   tgt->times.endtime < time_now + gsd->tgt_renew_threshold) {

		  krb5_creds *new_creds[2];
		  krb5_creds creds;

		  memset(new_creds, 0, sizeof(new_creds));
		  memset(&creds, 0 ,sizeof(creds));

		  /* renew the TGT */

		  if (((rc = krb5_copy_principal(context, (*tgt_creds)->server,
			&creds.server))) ||
		      ((rc = krb5_copy_principal(context, (*tgt_creds)->client,
			&creds.client))) ||
		      ((rc = krb5_get_cred_via_tkt(context, tgt,
		        FLAGS2OPTS(tgt->ticket_flags)|KDC_OPT_RENEW,
		        tgt->addresses, &creds, &new_creds[0])))) {

		     ERROR((SGE_EVENT, MSG_KRB_COULDNOTRENEWTGTFORJOBXY_DS, 
                  sge_u32c(lGetUlong(job, JB_job_number)),
			         error_message(rc)));

		  }

		  krb5_free_cred_contents(context, &creds);

		  if (rc == 0) {
                     krb5_data outbuf;

		     /* store the new TGT back into the job entry */

		     outbuf.length = 0;

		     if ((rc = krb_encrypt_tgt_creds(new_creds, &outbuf))) {

			ERROR((SGE_EVENT, MSG_KRB_COULDNOTECRYPTTGTFORJOBXY_DS,
                sge_u32c(lGetUlong(job, JB_job_number)),
			       error_message(rc)));

		     } else {

			lSetString(job, JB_tgt,
			      krb_bin2str(outbuf.data, outbuf.length, NULL));
                     }

		     /* if we are called by the execd, also store the
			new TGT in the credentials cache of the user */

                     if (!strcmp(prognames[EXECD], gsd->progname)) {
                         
                        int retries = MAX_NIS_RETRIES;
			struct passwd *pw = NULL;

			while (retries-- && !pw)
			   pw = getpwnam(lGetString(job, JB_owner));

			if (pw) {

			   if ((krb_store_forwarded_tgt(pw->pw_uid,
				    lGetUlong(job, JB_job_number),
				    new_creds))) {

			       ERROR((SGE_EVENT, MSG_KRB_COULDNOTSTORERENEWEDTGTFORXJOBY_SD,
                                      lGetString(job, JB_owner),
				      sge_u32c(lGetUlong(job, JB_job_number))));
                           }

                        } else {

			   ERROR((SGE_EVENT, MSG_KRB_COULDNOTGETUSERIDFORXY_SD , lGetString(job, JB_owner),
				  sge_u32c(lGetUlong(job, JB_job_number))));
                        }
		     }

		     if (outbuf.length)
			krb5_xfree(outbuf.data);

		  }

      if (!mconf_get_simulate_jobs()) {
         job_write_spool_file(job, 0, NULL, SPOOL_DEFAULT);;
      }

		  if (new_creds[0])
		     krb5_free_creds(context, new_creds[0]);

	       }
	    }
         }

         if (tgtbuf.length)
            krb5_xfree(tgtbuf.data);

         if (tgt_creds)
            krb5_free_tgt_creds(context, tgt_creds);

      }

   }
Esempio n. 3
0
static krb5_error_code
krb5_validate_or_renew_creds(krb5_context context, krb5_creds *creds,
			     krb5_principal client, krb5_ccache ccache,
			     char *in_tkt_service, int validate)
{
    krb5_error_code ret;
    krb5_creds in_creds; /* only client and server need to be filled in */
    krb5_creds *out_creds = 0; /* for check before dereferencing below */
    krb5_creds **tgts;

    memset((char *)&in_creds, 0, sizeof(krb5_creds));

    in_creds.server = NULL;
    tgts = NULL;

    in_creds.client = client;

    if (in_tkt_service) {
	/* this is ugly, because so are the data structures involved.  I'm
	   in the library, so I'm going to manipulate the data structures
	   directly, otherwise, it will be worse. */

        if ((ret = krb5_parse_name(context, in_tkt_service, &in_creds.server)))
	    goto cleanup;

	/* stuff the client realm into the server principal.
	   realloc if necessary */
	if (in_creds.server->realm.length < in_creds.client->realm.length)
	    if ((in_creds.server->realm.data =
		 (char *) realloc(in_creds.server->realm.data,
				  in_creds.client->realm.length)) == NULL) {
		ret = ENOMEM;
		goto cleanup;
	    }

	in_creds.server->realm.length = in_creds.client->realm.length;
	memcpy(in_creds.server->realm.data, in_creds.client->realm.data,
	       in_creds.client->realm.length);
    } else {
	if ((ret = krb5_build_principal_ext(context, &in_creds.server,
					   in_creds.client->realm.length,
					   in_creds.client->realm.data,
					   KRB5_TGS_NAME_SIZE,
					   KRB5_TGS_NAME,
					   in_creds.client->realm.length,
					   in_creds.client->realm.data,
					    0)))
	    goto cleanup;
    }

    if (validate)
	ret = krb5_get_cred_from_kdc_validate(context, ccache, 
					      &in_creds, &out_creds, &tgts);
    else
	ret = krb5_get_cred_from_kdc_renew(context, ccache, 
					   &in_creds, &out_creds, &tgts);
   
    /* ick.  copy the struct contents, free the container */
    if (out_creds) {
	*creds = *out_creds;
	krb5_xfree(out_creds);
    }

cleanup:

    if (in_creds.server)
	krb5_free_principal(context, in_creds.server);
    if (tgts)
	krb5_free_tgt_creds(context, tgts);

    return(ret);
}
Esempio n. 4
0
krb5_error_code KRB5_CALLCONV
krb5_get_credentials(krb5_context context, krb5_flags options,
		     krb5_ccache ccache, krb5_creds *in_creds,
		     krb5_creds **out_creds)
{
    krb5_error_code retval;
    krb5_creds mcreds;
    krb5_creds *ncreds;
    krb5_creds **tgts;
    krb5_flags fields;
    int not_ktype;

    retval = krb5_get_credentials_core(context, options,
				       in_creds,
				       &mcreds, &fields);

    if (retval) return retval;

    if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL)
	return ENOMEM;

    memset((char *)ncreds, 0, sizeof(krb5_creds));
    ncreds->magic = KV5M_CREDS;

    /* The caller is now responsible for cleaning up in_creds */
    if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
					ncreds))) {
	krb5_xfree(ncreds);
	ncreds = in_creds;
    } else {
	*out_creds = ncreds;
    }

    if ((retval != KRB5_CC_NOTFOUND && retval != KRB5_CC_NOT_KTYPE)
	|| options & KRB5_GC_CACHED)
	return retval;

    if (retval == KRB5_CC_NOT_KTYPE)
	not_ktype = 1;
    else
	not_ktype = 0;

    retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts);
    if (tgts) {
	register int i = 0;
	krb5_error_code rv2;
	while (tgts[i]) {
	    if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i]))) {
		retval = rv2;
		break;
	    }
	    i++;
	}
	krb5_free_tgt_creds(context, tgts);
    }
    /*
     * Translate KRB5_CC_NOTFOUND if we previously got
     * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to
     * handle the case where there is no TGT in the ccache and the
     * input enctype didn't match.  This handling is necessary because
     * some callers, such as GSSAPI, iterate through enctypes and
     * KRB5_CC_NOTFOUND passed through from the
     * krb5_get_cred_from_kdc() is semantically incorrect, since the
     * actual failure was the non-existence of a ticket of the correct
     * enctype rather than the missing TGT.
     */
    if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE)
	&& not_ktype)
	retval = KRB5_CC_NOT_KTYPE;

    if (!retval) {
        /* the purpose of the krb5_get_credentials call is to 
         * obtain a set of credentials for the caller.  the 
         * krb5_cc_store_cred() call is to optimize performance
         * for future calls.  Ignore any errors, since the credentials
         * are still valid even if we fail to store them in the cache.
         */
	krb5_cc_store_cred(context, ccache, *out_creds);
    }
    return retval;
}
Esempio n. 5
0
static krb5_error_code
krb5_rd_cred_basic(krb5_context context, krb5_data *pcreddata,
                   krb5_key pkey, krb5_replay_data *replaydata,
                   krb5_creds ***pppcreds)
{
    krb5_error_code       retval = 0;
    krb5_cred           * pcred = NULL;
    krb5_int32            ncreds = 0;
    krb5_int32            i = 0;
    krb5_cred_enc_part    encpart;

    /* decode cred message */
    if ((retval = decode_krb5_cred(pcreddata, &pcred)))
        return retval;

    memset(&encpart, 0, sizeof(encpart));

    if ((retval = decrypt_credencdata(context, pcred, pkey, &encpart)))
        goto cleanup_cred;


    replaydata->timestamp = encpart.timestamp;
    replaydata->usec = encpart.usec;
    replaydata->seq = encpart.nonce;

    /*
     * Allocate the list of creds.  The memory is allocated so that
     * krb5_free_tgt_creds can be used to free the list.
     */
    for (ncreds = 0; pcred->tickets[ncreds]; ncreds++);

    if ((*pppcreds =
         (krb5_creds **)malloc((size_t)(sizeof(krb5_creds *) *
                                        (ncreds + 1)))) == NULL) {
        retval = ENOMEM;
        goto cleanup_cred;
    }
    (*pppcreds)[0] = NULL;

    /*
     * For each credential, create a strcture in the list of
     * credentials and copy the information.
     */
    while (i < ncreds) {
        krb5_cred_info  * pinfo;
        krb5_creds      * pcur;
        krb5_data       * pdata;

        if ((pcur = (krb5_creds *)calloc(1, sizeof(krb5_creds))) == NULL) {
            retval = ENOMEM;
            goto cleanup;
        }

        (*pppcreds)[i] = pcur;
        (*pppcreds)[i+1] = 0;
        pinfo = encpart.ticket_info[i++];

        if ((retval = krb5_copy_principal(context, pinfo->client,
                                          &pcur->client)))
            goto cleanup;

        if ((retval = krb5_copy_principal(context, pinfo->server,
                                          &pcur->server)))
            goto cleanup;

        if ((retval = krb5_copy_keyblock_contents(context, pinfo->session,
                                                  &pcur->keyblock)))
            goto cleanup;

        if ((retval = krb5_copy_addresses(context, pinfo->caddrs,
                                          &pcur->addresses)))
            goto cleanup;

        if ((retval = encode_krb5_ticket(pcred->tickets[i - 1], &pdata)))
            goto cleanup;

        pcur->ticket = *pdata;
        free(pdata);


        pcur->is_skey = FALSE;
        pcur->magic = KV5M_CREDS;
        pcur->times = pinfo->times;
        pcur->ticket_flags = pinfo->flags;
        pcur->authdata = NULL;   /* not used */
        memset(&pcur->second_ticket, 0, sizeof(pcur->second_ticket));
    }

    /*
     * NULL terminate the list
     */
    (*pppcreds)[i] = NULL;

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

cleanup_cred:
    krb5_free_cred(context, pcred);
    krb5_free_cred_enc_part(context, &encpart);

    return retval;
}
Esempio n. 6
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;
}
Esempio n. 7
0
File: rd_cred.c Progetto: krb5/krb5
/* Produce a list of credentials from a KRB-CRED message and its enc_part. */
static krb5_error_code
make_cred_list(krb5_context context, krb5_cred *krbcred,
               krb5_cred_enc_part *encpart, krb5_creds ***creds_out)
{
    krb5_error_code ret = 0;
    krb5_creds **list = NULL;
    krb5_cred_info *info;
    krb5_data *ticket_data;
    size_t i, count;

    *creds_out = NULL;

    /* Allocate the list of creds. */
    for (count = 0; krbcred->tickets[count] != NULL; count++);
    list = k5calloc(count + 1, sizeof(*list), &ret);
    if (list == NULL)
        goto cleanup;

    /* For each credential, create a strcture in the list of credentials and
     * copy the information. */
    for (i = 0; i < count; i++) {
        list[i] = k5alloc(sizeof(*list[i]), &ret);
        if (list[i] == NULL)
            goto cleanup;

        info = encpart->ticket_info[i];
        ret = krb5_copy_principal(context, info->client, &list[i]->client);
        if (ret)
            goto cleanup;

        ret = krb5_copy_principal(context, info->server, &list[i]->server);
        if (ret)
            goto cleanup;

        ret = krb5_copy_keyblock_contents(context, info->session,
                                          &list[i]->keyblock);
        if (ret)
            goto cleanup;

        ret = krb5_copy_addresses(context, info->caddrs, &list[i]->addresses);
        if (ret)
            goto cleanup;

        ret = encode_krb5_ticket(krbcred->tickets[i], &ticket_data);
        if (ret)
            goto cleanup;
        list[i]->ticket = *ticket_data;
        free(ticket_data);

        list[i]->is_skey = FALSE;
        list[i]->magic = KV5M_CREDS;
        list[i]->times = info->times;
        list[i]->ticket_flags = info->flags;
        list[i]->authdata = NULL;
        list[i]->second_ticket = empty_data();
    }

    *creds_out = list;
    list = NULL;

cleanup:
    krb5_free_tgt_creds(context, list);
    return ret;
}
Esempio n. 8
0
File: rd_cred.c Progetto: krb5/krb5
/* Validate a KRB-CRED message in creddata, and return a list of forwarded
 * credentials along with replay cache information. */
krb5_error_code KRB5_CALLCONV
krb5_rd_cred(krb5_context context, krb5_auth_context authcon,
             krb5_data *creddata, krb5_creds ***creds_out,
             krb5_replay_data *replaydata_out)
{
    krb5_error_code ret = 0;
    krb5_creds **credlist = NULL;
    krb5_cred *krbcred = NULL;
    krb5_cred_enc_part *encpart = NULL;
    krb5_replay_data rdata;
    const krb5_int32 flags = authcon->auth_context_flags;

    *creds_out = NULL;

    if (((flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
         (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
        replaydata_out == NULL)
        return KRB5_RC_REQUIRED;

    ret = decode_krb5_cred(creddata, &krbcred);
    if (ret)
        goto cleanup;

    ret = decrypt_encpart(context, &krbcred->enc_part, authcon, &encpart);
    if (ret)
        goto cleanup;

    ret = make_cred_list(context, krbcred, encpart, &credlist);
    if (ret)
        goto cleanup;

    if (authcon->recv_subkey != NULL || authcon->key != NULL) {
        rdata.timestamp = encpart->timestamp;
        ret = k5_privsafe_check_replay(context, authcon, &rdata,
                                       &krbcred->enc_part, NULL);
        if (ret)
            goto cleanup;
    }

    if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
        if (authcon->remote_seq_number != (uint32_t)encpart->nonce) {
            ret = KRB5KRB_AP_ERR_BADORDER;
            goto cleanup;
        }
        authcon->remote_seq_number++;
    }

    *creds_out = credlist;
    credlist = NULL;
    if ((flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
        (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
        replaydata_out->timestamp = encpart->timestamp;
        replaydata_out->usec = encpart->usec;
        replaydata_out->seq = encpart->nonce;
    }

cleanup:
    krb5_free_tgt_creds(context, credlist);
    krb5_free_cred(context, krbcred);
    krb5_free_cred_enc_part(context, encpart);
    free(encpart);              /* krb5_free_cred_enc_part doesn't do this */
    return ret;
}