Пример #1
0
 krb5_error_code krb5_rd_req_return_keyblock_from_keytab(krb5_context context,
							krb5_auth_context *auth_context,
							const krb5_data *inbuf,
							krb5_const_principal server,
							krb5_keytab keytab,
							krb5_flags *ap_req_options,
							krb5_ticket **ticket, 
							krb5_keyblock **keyblock)
{
	krb5_error_code ret;
	krb5_kvno kvno;
	krb5_enctype enctype;
	krb5_keyblock *local_keyblock;

	ret = krb5_rd_req(context, 
			  auth_context, 
			  inbuf, 
			  server, 
			  keytab, 
			  ap_req_options, 
			  ticket);
	if (ret) {
		return ret;
	}
	
#ifdef KRB5_TICKET_HAS_KEYINFO
	enctype = (*ticket)->enc_part.enctype;
	kvno = (*ticket)->enc_part.kvno;
#else
	ret = smb_krb5_get_keyinfo_from_ap_req(context, inbuf, &kvno, &enctype);
	if (ret) {
		return ret;
	}
#endif

	ret = get_key_from_keytab(context, 
				  server,
				  enctype,
				  kvno,
				  &local_keyblock);
	if (ret) {
		DEBUG(0,("krb5_rd_req_return_keyblock_from_keytab: failed to call get_key_from_keytab\n"));
		goto out;
	}

out:
	if (ret && local_keyblock != NULL) {
	        krb5_free_keyblock(context, local_keyblock);
	} else {
		*keyblock = local_keyblock;
	}

	return ret;
}
Пример #2
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_rd_req_ctx(krb5_context context,
		krb5_auth_context *auth_context,
		const krb5_data *inbuf,
		krb5_const_principal server,
		krb5_rd_req_in_ctx inctx,
		krb5_rd_req_out_ctx *outctx)
{
    krb5_error_code ret;
    krb5_ap_req ap_req;
    krb5_rd_req_out_ctx o = NULL;
    krb5_keytab id = NULL, keytab = NULL;
    krb5_principal service = NULL;

    *outctx = NULL;

    o = calloc(1, sizeof(*o));
    if (o == NULL) {
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    if (*auth_context == NULL) {
	ret = krb5_auth_con_init(context, auth_context);
	if (ret)
	    goto out;
    }

    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
    if(ret)
	goto out;

    /* Save that principal that was in the request */
    ret = _krb5_principalname2krb5_principal(context,
					     &o->server,
					     ap_req.ticket.sname,
					     ap_req.ticket.realm);
    if (ret)
	goto out;

    if (ap_req.ap_options.use_session_key &&
	(*auth_context)->keyblock == NULL) {
	ret = KRB5KRB_AP_ERR_NOKEY;
	krb5_set_error_message(context, ret,
			       N_("krb5_rd_req: user to user auth "
				  "without session key given", ""));
	goto out;
    }

    if (inctx && inctx->keytab)
	id = inctx->keytab;

    if((*auth_context)->keyblock){
	ret = krb5_copy_keyblock(context,
				 (*auth_context)->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else if(inctx && inctx->keyblock){
	ret = krb5_copy_keyblock(context,
				 inctx->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else {

	if(id == NULL) {
	    krb5_kt_default(context, &keytab);
	    id = keytab;
	}
	if (id == NULL)
	    goto out;

	if (server == NULL) {
	    ret = _krb5_principalname2krb5_principal(context,
						     &service,
						     ap_req.ticket.sname,
						     ap_req.ticket.realm);
	    if (ret)
		goto out;
	    server = service;
	}

	ret = get_key_from_keytab(context,
				  &ap_req,
				  server,
				  id,
				  &o->keyblock);
	if (ret) {
	    /* If caller specified a server, fail. */
	    if (service == NULL && (context->flags & KRB5_CTX_F_RD_REQ_IGNORE) == 0)
		goto out;
	    /* Otherwise, fall back to iterating over the keytab. This
	     * have serious performace issues for larger keytab.
	     */
	    o->keyblock = NULL;
	}
    }

    if (o->keyblock) {
	/*
	 * We got an exact keymatch, use that.
	 */

	ret = krb5_verify_ap_req2(context,
				  auth_context,
				  &ap_req,
				  server,
				  o->keyblock,
				  0,
				  &o->ap_req_options,
				  &o->ticket,
				  KRB5_KU_AP_REQ_AUTH);

	if (ret)
	    goto out;

    } else {
	/*
	 * Interate over keytab to find a key that can decrypt the request.
	 */

	krb5_keytab_entry entry;
	krb5_kt_cursor cursor;
	int done = 0, kvno = 0;

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

	if (ap_req.ticket.enc_part.kvno)
	    kvno = *ap_req.ticket.enc_part.kvno;

	ret = krb5_kt_start_seq_get(context, id, &cursor);
	if (ret)
	    goto out;

	done = 0;
	while (!done) {
	    krb5_principal p;

	    ret = krb5_kt_next_entry(context, id, &entry, &cursor);
	    if (ret) {
		_krb5_kt_principal_not_found(context, ret, id, o->server,
					     ap_req.ticket.enc_part.etype,
					     kvno);
		krb5_kt_end_seq_get(context, id, &cursor);
		goto out;
	    }

	    if (entry.keyblock.keytype != ap_req.ticket.enc_part.etype) {
		krb5_kt_free_entry (context, &entry);
		continue;
	    }

	    ret = krb5_verify_ap_req2(context,
				      auth_context,
				      &ap_req,
				      server,
				      &entry.keyblock,
				      0,
				      &o->ap_req_options,
				      &o->ticket,
				      KRB5_KU_AP_REQ_AUTH);
	    if (ret) {
		krb5_kt_free_entry(context, &entry);
		continue;
	    }

	    /*
	     * Found a match, save the keyblock for PAC processing,
	     * and update the service principal in the ticket to match
	     * whatever is in the keytab.
	     */

	    ret = krb5_copy_keyblock(context,
				     &entry.keyblock,
				     &o->keyblock);
	    if (ret) {
		krb5_kt_free_entry(context, &entry);
		krb5_kt_end_seq_get(context, id, &cursor);
		goto out;
	    }

	    ret = krb5_copy_principal(context, entry.principal, &p);
	    if (ret) {
		krb5_kt_free_entry(context, &entry);
		krb5_kt_end_seq_get(context, id, &cursor);
		goto out;
	    }
	    krb5_free_principal(context, o->ticket->server);
	    o->ticket->server = p;
	    
	    krb5_kt_free_entry(context, &entry);

	    done = 1;
	}
	krb5_kt_end_seq_get(context, id, &cursor);
    }

    /* If there is a PAC, verify its server signature */
    if (inctx == NULL || inctx->check_pac) {
	krb5_pac pac;
	krb5_data data;

	ret = krb5_ticket_get_authorization_data_type(context,
						      o->ticket,
						      KRB5_AUTHDATA_WIN2K_PAC,
						      &data);
	if (ret == 0) {
	    ret = krb5_pac_parse(context, data.data, data.length, &pac);
	    krb5_data_free(&data);
	    if (ret)
		goto out;

	    ret = krb5_pac_verify(context,
				  pac,
				  o->ticket->ticket.authtime,
				  o->ticket->client,
				  o->keyblock,
				  NULL);
	    krb5_pac_free(context, pac);
	    if (ret == 0)
		o->flags |= KRB5_RD_REQ_OUT_PAC_VALID;
	    ret = 0;
	} else
	    ret = 0;
    }
 out:

    if (ret || outctx == NULL) {
	krb5_rd_req_out_ctx_free(context, o);
    } else
	*outctx = o;

    free_AP_REQ(&ap_req);

    if (service)
	krb5_free_principal(context, service);

    if (keytab)
	krb5_kt_close(context, keytab);

    return ret;
}
Пример #3
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_ctx(krb5_context context,
		krb5_auth_context *auth_context,
		const krb5_data *inbuf,
		krb5_const_principal server,
		krb5_rd_req_in_ctx inctx,
		krb5_rd_req_out_ctx *outctx)
{
    krb5_error_code ret;
    krb5_ap_req ap_req;
    krb5_principal service = NULL;
    krb5_rd_req_out_ctx o = NULL;

    ret = _krb5_rd_req_out_ctx_alloc(context, &o);
    if (ret)
	goto out;

    if (*auth_context == NULL) {
	ret = krb5_auth_con_init(context, auth_context);
	if (ret)
	    goto out;
    }

    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
    if(ret)
	goto out;

    if(server == NULL){
	ret = _krb5_principalname2krb5_principal(context,
						 &service,
						 ap_req.ticket.sname,
						 ap_req.ticket.realm);
	if (ret)
	    goto out;
	server = service;
    }
    if (ap_req.ap_options.use_session_key &&
	(*auth_context)->keyblock == NULL) {
	krb5_set_error_string(context, "krb5_rd_req: user to user auth "
			      "without session key given");
	ret = KRB5KRB_AP_ERR_NOKEY;
	goto out;
    }

    if((*auth_context)->keyblock){
	ret = krb5_copy_keyblock(context,
				 (*auth_context)->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else if(inctx->keyblock){
	ret = krb5_copy_keyblock(context,
				 inctx->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else {
	krb5_keytab keytab = NULL;

	if (inctx && inctx->keytab)
	    keytab = inctx->keytab;

	ret = get_key_from_keytab(context, 
				  auth_context, 
				  &ap_req,
				  server,
				  keytab,
				  &o->keyblock);
	if(ret)
	    goto out;
    }

    ret = krb5_verify_ap_req2(context,
			      auth_context,
			      &ap_req,
			      server,
			      o->keyblock,
			      0,
			      &o->ap_req_options,
			      &o->ticket,
			      KRB5_KU_AP_REQ_AUTH);

    if (ret)
	goto out;

    /* If there is a PAC, verify its server signature */
    if (inctx->check_pac) {
	krb5_pac pac;
	krb5_data data;

	ret = krb5_ticket_get_authorization_data_type(context,
						      o->ticket,
						      KRB5_AUTHDATA_WIN2K_PAC,
						      &data);
	if (ret == 0) {
	    ret = krb5_pac_parse(context, data.data, data.length, &pac);
	    krb5_data_free(&data);
	    if (ret)
		goto out;
	
	    ret = krb5_pac_verify(context,
				  pac, 
				  o->ticket->ticket.authtime,
				  o->ticket->client, 
				  o->keyblock, 
				  NULL);
	    krb5_pac_free(context, pac);
	    if (ret)
		goto out;
	}
	ret = 0;
    }
out:
    if (ret || outctx == NULL) {
	krb5_rd_req_out_ctx_free(context, o);
    } else 
	*outctx = o;

    free_AP_REQ(&ap_req);
    if(service)
	krb5_free_principal(context, service);
    return ret;
}
Пример #4
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req(krb5_context context,
	    krb5_auth_context *auth_context,
	    const krb5_data *inbuf,
	    krb5_const_principal server,
	    krb5_keytab keytab,
	    krb5_flags *ap_req_options,
	    krb5_ticket **ticket)
{
    krb5_error_code ret;
    krb5_ap_req ap_req;
    krb5_keyblock *keyblock = NULL;
    krb5_principal service = NULL;

    if (*auth_context == NULL) {
	ret = krb5_auth_con_init(context, auth_context);
	if (ret)
	    return ret;
    }

    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
    if(ret)
	return ret;

    if(server == NULL){
	_krb5_principalname2krb5_principal(&service,
					   ap_req.ticket.sname,
					   ap_req.ticket.realm);
	server = service;
    }
    if (ap_req.ap_options.use_session_key &&
	(*auth_context)->keyblock == NULL) {
	krb5_set_error_string(context, "krb5_rd_req: user to user auth "
			      "without session key given");
	ret = KRB5KRB_AP_ERR_NOKEY;
	goto out;
    }

    if((*auth_context)->keyblock == NULL){
	ret = get_key_from_keytab(context, 
				  auth_context, 
				  &ap_req,
				  server,
				  keytab,
				  &keyblock);
	if(ret)
	    goto out;
    } else {
	ret = krb5_copy_keyblock(context,
				 (*auth_context)->keyblock,
				 &keyblock);
	if (ret)
	    goto out;
    }

    ret = krb5_verify_ap_req(context,
			     auth_context,
			     &ap_req,
			     server,
			     keyblock,
			     0,
			     ap_req_options,
			     ticket);

    krb5_free_keyblock(context, keyblock);

out:
    free_AP_REQ(&ap_req);
    if(service)
	krb5_free_principal(context, service);
    return ret;
}