Exemple #1
0
krb5_error_code KRB5_CALLCONV
krb5_authdata_context_copy(krb5_context kcontext,
                           krb5_authdata_context src,
                           krb5_authdata_context *pdst)
{
    int i;
    krb5_error_code code;
    krb5_authdata_context dst;

    /* XXX we need to init a new context because we can't copy plugins */
    code = krb5_authdata_context_init(kcontext, &dst);
    if (code != 0)
        return code;

    for (i = 0; i < src->n_modules; i++) {
        struct _krb5_authdata_context_module *module = &src->modules[i];

        code = k5_copy_ad_module_data(kcontext, src, module, dst);
        if (code != 0)
            break;
    }

    if (code != 0) {
        krb5_authdata_context_free(kcontext, dst);
        return code;
    }

    *pdst = dst;

    return 0;
}
Exemple #2
0
/*
 * Import serialized authdata context
 */
static krb5_error_code
import_name_composite(krb5_context context,
                      unsigned char *enc_data, size_t enc_length,
                      krb5_authdata_context *pad_context)
{
    krb5_authdata_context ad_context;
    krb5_error_code code;
    krb5_data data;

    code = krb5_authdata_context_init(context, &ad_context);
    if (code != 0)
        return code;

    data.data = (char *)enc_data;
    data.length = enc_length;

    code = krb5_authdata_import_attributes(context,
                                           ad_context,
                                           AD_USAGE_MASK,
                                           &data);
    if (code != 0) {
        krb5_authdata_context_free(context, ad_context);
        return code;
    }

    *pad_context = ad_context;

    return 0;
}
Exemple #3
0
OM_uint32 KRB5_CALLCONV
krb5_gss_release_any_name_mapping(OM_uint32 *minor_status,
                                  gss_name_t name,
                                  gss_buffer_t type_id,
                                  gss_any_t *input)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    char *kmodule;

    if (minor_status != NULL)
        *minor_status = 0;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0) {
            *minor_status = code;
            k5_mutex_unlock(&kname->lock);
            krb5_free_context(context);
            return GSS_S_UNAVAILABLE;
        }
    }

    kmodule = (char *)type_id->value;
    if (kmodule[type_id->length] != '\0') {
        k5_mutex_unlock(&kname->lock);
        krb5_free_context(context);
        return GSS_S_UNAVAILABLE;
    }

    code = krb5_authdata_free_internal(context,
                                       kname->ad_context,
                                       kmodule,
                                       *input);
    if (code == 0)
        *input = NULL;

    k5_mutex_unlock(&kname->lock);
    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);

}
Exemple #4
0
OM_uint32 KRB5_CALLCONV
krb5_gss_set_name_attribute(OM_uint32 *minor_status,
                            gss_name_t name,
                            int complete,
                            gss_buffer_t attr,
                            gss_buffer_t value)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    krb5_data kattr;
    krb5_data kvalue;

    if (minor_status != NULL)
        *minor_status = 0;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0) {
            *minor_status = code;
            k5_mutex_unlock(&kname->lock);
            krb5_free_context(context);
            return GSS_S_UNAVAILABLE;
        }
    }

    kattr.data = (char *)attr->value;
    kattr.length = attr->length;

    kvalue.data = (char *)value->value;
    kvalue.length = value->length;

    code = krb5_authdata_set_attribute(context,
                                       kname->ad_context,
                                       complete,
                                       &kattr,
                                       &kvalue);

    k5_mutex_unlock(&kname->lock);
    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}
Exemple #5
0
OM_uint32 KRB5_CALLCONV
krb5_gss_inquire_name(OM_uint32 *minor_status,
                      gss_name_t name,
                      int *name_is_MN,
                      gss_OID *MN_mech,
                      gss_buffer_set_t *attrs)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    krb5_data *kattrs = NULL;

    if (minor_status != NULL)
        *minor_status = 0;

    if (attrs != NULL)
        *attrs = GSS_C_NO_BUFFER_SET;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0)
            goto cleanup;
    }

    code = krb5_authdata_get_attribute_types(context,
                                             kname->ad_context,
                                             &kattrs);
    if (code != 0)
        goto cleanup;

    code = data_list_to_buffer_set(context, kattrs, attrs);
    kattrs = NULL;
    if (code != 0)
        goto cleanup;

cleanup:
    k5_mutex_unlock(&kname->lock);
    krb5int_free_data_list(context, kattrs);

    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}
Exemple #6
0
OM_uint32
krb5_gss_delete_name_attribute(OM_uint32 *minor_status,
                               gss_name_t name,
                               gss_buffer_t attr)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    krb5_data kattr;

    if (minor_status != NULL)
        *minor_status = 0;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (!kg_validate_name(name)) {
        *minor_status = (OM_uint32)G_VALIDATE_FAILED;
        krb5_free_context(context);
        return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0) {
            *minor_status = code;
            k5_mutex_unlock(&kname->lock);
            krb5_free_context(context);
            return GSS_S_UNAVAILABLE;
        }
    }

    kattr.data = (char *)attr->value;
    kattr.length = attr->length;

    code = krb5_authdata_delete_attribute(context,
                                          kname->ad_context,
                                          &kattr);

    k5_mutex_unlock(&kname->lock);
    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}
Exemple #7
0
/*
 * Internalize an authdata context.
 */
static krb5_error_code
krb5_authdata_context_internalize(krb5_context kcontext,
                                  krb5_pointer *ptr,
                                  krb5_octet **buffer,
                                  size_t *lenremain)
{
    krb5_error_code code;
    krb5_authdata_context context;
    krb5_int32 ibuf;
    krb5_octet *bp;
    size_t remain;

    bp = *buffer;
    remain = *lenremain;

    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
    if (code != 0)
        return code;

    if (ibuf != KV5M_AUTHDATA_CONTEXT)
        return EINVAL;

    code = krb5_authdata_context_init(kcontext, &context);
    if (code != 0)
        return code;

    code = k5_ad_internalize(kcontext, context, AD_USAGE_MASK,
                             &bp, &remain);
    if (code != 0) {
        krb5_authdata_context_free(kcontext, context);
        return code;
    }

    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
    if (code != 0)
        return code;

    if (ibuf != KV5M_AUTHDATA_CONTEXT) {
        krb5_authdata_context_free(kcontext, context);
        return EINVAL;
    }

    *buffer = bp;
    *lenremain = remain;
    *ptr = context;

    return 0;
}
Exemple #8
0
OM_uint32 KRB5_CALLCONV
krb5_gss_get_name_attribute(OM_uint32 *minor_status,
                            gss_name_t name,
                            gss_buffer_t attr,
                            int *authenticated,
                            int *complete,
                            gss_buffer_t value,
                            gss_buffer_t display_value,
                            int *more)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    krb5_data kattr;
    krb5_boolean kauthenticated;
    krb5_boolean kcomplete;
    krb5_data kvalue;
    krb5_data kdisplay_value;

    if (minor_status != NULL)
        *minor_status = 0;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        krb5_free_context(context);
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0) {
            *minor_status = code;
            k5_mutex_unlock(&kname->lock);
            krb5_free_context(context);
            return GSS_S_UNAVAILABLE;
        }
    }

    kattr.data = (char *)attr->value;
    kattr.length = attr->length;

    kauthenticated = FALSE;
    kcomplete = FALSE;

    code = krb5_authdata_get_attribute(context,
                                       kname->ad_context,
                                       &kattr,
                                       &kauthenticated,
                                       &kcomplete,
                                       value ? &kvalue : NULL,
                                       display_value ? &kdisplay_value : NULL,
                                       more);
    if (code == 0) {
        if (value != NULL)
            code = data_to_gss(&kvalue, value);

        if (authenticated != NULL)
            *authenticated = kauthenticated;
        if (complete != NULL)
            *complete = kcomplete;

        if (display_value != NULL) {
            if (code == 0)
                code = data_to_gss(&kdisplay_value, display_value);
            else
                free(kdisplay_value.data);
        }
    }

    k5_mutex_unlock(&kname->lock);
    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}
Exemple #9
0
static krb5_error_code
rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
                   const krb5_ap_req *req, krb5_const_principal server,
                   krb5_keytab keytab, krb5_flags *ap_req_options,
                   krb5_ticket **ticket, int check_valid_flag)
{
    krb5_error_code       retval = 0;
    krb5_enctype         *desired_etypes = NULL;
    int                   desired_etypes_len = 0;
    int                   rfc4537_etypes_len = 0;
    krb5_enctype         *permitted_etypes = NULL;
    int                   permitted_etypes_len = 0;
    krb5_keyblock         decrypt_key;

    decrypt_key.enctype = ENCTYPE_NULL;
    decrypt_key.contents = NULL;
    req->ticket->enc_part2 = NULL;

    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
       do we need special processing here ?     */

    /* decrypt the ticket */
    if ((*auth_context)->key) { /* User to User authentication */
        if ((retval = krb5_decrypt_tkt_part(context,
                                            &(*auth_context)->key->keyblock,
                                            req->ticket)))
            goto cleanup;
        if (check_valid_flag) {
            decrypt_key = (*auth_context)->key->keyblock;
            (*auth_context)->key->keyblock.contents = NULL;
        }
        krb5_k_free_key(context, (*auth_context)->key);
        (*auth_context)->key = NULL;
    } else {
        retval = decrypt_ticket(context, req, server, keytab,
                                check_valid_flag ? &decrypt_key : NULL);
        if (retval)
            goto cleanup;
    }
    TRACE_RD_REQ_TICKET(context, req->ticket->enc_part2->client,
                        req->ticket->server, req->ticket->enc_part2->session);

    /* XXX this is an evil hack.  check_valid_flag is set iff the call
       is not from inside the kdc.  we can use this to determine which
       key usage to use */
#ifndef LEAN_CLIENT
    if ((retval = decrypt_authenticator(context, req,
                                        &((*auth_context)->authentp),
                                        check_valid_flag)))
        goto cleanup;
#endif
    if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
                                req->ticket->enc_part2->client)) {
        retval = KRB5KRB_AP_ERR_BADMATCH;
        goto cleanup;
    }

    if ((*auth_context)->remote_addr &&
        !krb5_address_search(context, (*auth_context)->remote_addr,
                             req->ticket->enc_part2->caddrs)) {
        retval = KRB5KRB_AP_ERR_BADADDR;
        goto cleanup;
    }

    if (!server) {
        server = req->ticket->server;
    }
    /* Get an rcache if necessary. */
    if (((*auth_context)->rcache == NULL)
        && ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME)
        && server) {
        if ((retval = krb5_get_server_rcache(context,
                                             krb5_princ_component(context,server,0),
                                             &(*auth_context)->rcache)))
            goto cleanup;
    }
    /* okay, now check cross-realm policy */

#if defined(_SINGLE_HOP_ONLY)

    /* Single hop cross-realm tickets only */

    {
        krb5_transited *trans = &(req->ticket->enc_part2->transited);

        /* If the transited list is empty, then we have at most one hop */
        if (trans->tr_contents.length > 0 && trans->tr_contents.data[0])
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
    }

#elif defined(_NO_CROSS_REALM)

    /* No cross-realm tickets */

    {
        char            * lrealm;
        krb5_data       * realm;
        krb5_transited  * trans;

        realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
        trans = &(req->ticket->enc_part2->transited);

        /*
         * If the transited list is empty, then we have at most one hop
         * So we also have to check that the client's realm is the local one
         */
        krb5_get_default_realm(context, &lrealm);
        if ((trans->tr_contents.length > 0 && trans->tr_contents.data[0]) ||
            !data_eq_string(*realm, lrealm)) {
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
        }
        free(lrealm);
    }

#else

    /* Hierarchical Cross-Realm */

    {
        krb5_data      * realm;
        krb5_transited * trans;

        realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
        trans = &(req->ticket->enc_part2->transited);

        /*
         * If the transited list is not empty, then check that all realms
         * transited are within the hierarchy between the client's realm
         * and the local realm.
         */
        if (trans->tr_contents.length > 0 && trans->tr_contents.data[0]) {
            retval = krb5_check_transited_list(context, &(trans->tr_contents),
                                               realm,
                                               krb5_princ_realm (context,server));
        }
    }

#endif

    if (retval)  goto cleanup;

    /* only check rcache if sender has provided one---some services
       may not be able to use replay caches (such as datagram servers) */

    if ((*auth_context)->rcache) {
        krb5_donot_replay  rep;
        krb5_tkt_authent   tktauthent;

        tktauthent.ticket = req->ticket;
        tktauthent.authenticator = (*auth_context)->authentp;
        if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
            retval = krb5_rc_hash_message(context,
                                          &req->authenticator.ciphertext,
                                          &rep.msghash);
            if (!retval) {
                retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
                free(rep.msghash);
            }
            free(rep.server);
            free(rep.client);
        }

        if (retval)
            goto cleanup;
    }

    retval = krb5int_validate_times(context, &req->ticket->enc_part2->times);
    if (retval != 0)
        goto cleanup;

    if ((retval = krb5_check_clockskew(context, (*auth_context)->authentp->ctime)))
        goto cleanup;

    if (check_valid_flag) {
        if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) {
            retval = KRB5KRB_AP_ERR_TKT_INVALID;
            goto cleanup;
        }

        if ((retval = krb5_authdata_context_init(context,
                                                 &(*auth_context)->ad_context)))
            goto cleanup;
        if ((retval = krb5int_authdata_verify(context,
                                              (*auth_context)->ad_context,
                                              AD_USAGE_MASK,
                                              auth_context,
                                              &decrypt_key,
                                              req)))
            goto cleanup;
    }

    /* read RFC 4537 etype list from sender */
    retval = decode_etype_list(context,
                               (*auth_context)->authentp,
                               &desired_etypes,
                               &rfc4537_etypes_len);
    if (retval != 0)
        goto cleanup;

    if (desired_etypes == NULL)
        desired_etypes = (krb5_enctype *)calloc(4, sizeof(krb5_enctype));
    else
        desired_etypes = (krb5_enctype *)realloc(desired_etypes,
                                                 (rfc4537_etypes_len + 4) *
                                                 sizeof(krb5_enctype));
    if (desired_etypes == NULL) {
        retval = ENOMEM;
        goto cleanup;
    }

    desired_etypes_len = rfc4537_etypes_len;

    /*
     * RFC 4537:
     *
     *   If the EtypeList is present and the server prefers an enctype from
     *   the client's enctype list over that of the AP-REQ authenticator
     *   subkey (if that is present) or the service ticket session key, the
     *   server MUST create a subkey using that enctype.  This negotiated
     *   subkey is sent in the subkey field of AP-REP message, and it is then
     *   used as the protocol key or base key [RFC3961] for subsequent
     *   communication.
     *
     *   If the enctype of the ticket session key is included in the enctype
     *   list sent by the client, it SHOULD be the last on the list;
     *   otherwise, this enctype MUST NOT be negotiated if it was not included
     *   in the list.
     *
     * The second paragraph does appear to contradict the first with respect
     * to whether it is legal to negotiate the ticket session key type if it
     * is absent in the EtypeList. A literal reading suggests that we can use
     * the AP-REQ subkey enctype. Also a client has no way of distinguishing
     * a server that does not RFC 4537 from one that has chosen the same
     * enctype as the ticket session key for the acceptor subkey, surely.
     */

    if ((*auth_context)->authentp->subkey != NULL) {
        desired_etypes[desired_etypes_len++] = (*auth_context)->authentp->subkey->enctype;
    }
    desired_etypes[desired_etypes_len++] = req->ticket->enc_part2->session->enctype;
    desired_etypes[desired_etypes_len] = ENCTYPE_NULL;

    if (((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) == 0) {
        if ((*auth_context)->permitted_etypes != NULL) {
            permitted_etypes = (*auth_context)->permitted_etypes;
        } else {
            retval = krb5_get_permitted_enctypes(context, &permitted_etypes);
            if (retval != 0)
                goto cleanup;
        }
        permitted_etypes_len = krb5int_count_etypes(permitted_etypes);
    } else {
        permitted_etypes = NULL;
        permitted_etypes_len = 0;
    }

    /* check if the various etypes are permitted */
    retval = negotiate_etype(context,
                             desired_etypes, desired_etypes_len,
                             rfc4537_etypes_len,
                             permitted_etypes, permitted_etypes_len,
                             &(*auth_context)->negotiated_etype);
    if (retval != 0)
        goto cleanup;
    TRACE_RD_REQ_NEGOTIATED_ETYPE(context, (*auth_context)->negotiated_etype);

    assert((*auth_context)->negotiated_etype != ENCTYPE_NULL);

    (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
    if ((*auth_context)->authentp->subkey) {
        TRACE_RD_REQ_SUBKEY(context, (*auth_context)->authentp->subkey);
        if ((retval = krb5_k_create_key(context,
                                        (*auth_context)->authentp->subkey,
                                        &((*auth_context)->recv_subkey))))
            goto cleanup;
        retval = krb5_k_create_key(context, (*auth_context)->authentp->subkey,
                                   &((*auth_context)->send_subkey));
        if (retval) {
            krb5_k_free_key(context, (*auth_context)->recv_subkey);
            (*auth_context)->recv_subkey = NULL;
            goto cleanup;
        }
    } else {
        (*auth_context)->recv_subkey = 0;
        (*auth_context)->send_subkey = 0;
    }

    if ((retval = krb5_k_create_key(context, req->ticket->enc_part2->session,
                                    &((*auth_context)->key))))
        goto cleanup;

    debug_log_authz_data("ticket", req->ticket->enc_part2->authorization_data);

    /*
     * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used
     * then the default sequence number is the one's complement of the
     * sequence number sent ot us.
     */
    if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) &&
        (*auth_context)->remote_seq_number) {
        (*auth_context)->local_seq_number ^=
            (*auth_context)->remote_seq_number;
    }

    if (ticket)
        if ((retval = krb5_copy_ticket(context, req->ticket, ticket)))
            goto cleanup;
    if (ap_req_options) {
        *ap_req_options = req->ap_options & AP_OPTS_WIRE_MASK;
        if (rfc4537_etypes_len != 0)
            *ap_req_options |= AP_OPTS_ETYPE_NEGOTIATION;
        if ((*auth_context)->negotiated_etype !=
            krb5_k_key_enctype(context, (*auth_context)->key))
            *ap_req_options |= AP_OPTS_USE_SUBKEY;
    }

    retval = 0;

cleanup:
    if (desired_etypes != NULL)
        free(desired_etypes);
    if (permitted_etypes != NULL &&
        permitted_etypes != (*auth_context)->permitted_etypes)
        free(permitted_etypes);
    if (retval) {
        /* only free if we're erroring out...otherwise some
           applications will need the output. */
        if (req->ticket->enc_part2)
            krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
        req->ticket->enc_part2 = NULL;
    }
    if (check_valid_flag)
        krb5_free_keyblock_contents(context, &decrypt_key);

    return retval;
}
Exemple #10
0
OM_uint32
krb5_gss_map_name_to_any(OM_uint32 *minor_status,
                         gss_name_t name,
                         int authenticated,
                         gss_buffer_t type_id,
                         gss_any_t *output)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    char *kmodule;

    if (minor_status != NULL)
        *minor_status = 0;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (!kg_validate_name(name)) {
        *minor_status = (OM_uint32)G_VALIDATE_FAILED;
        krb5_free_context(context);
        return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0) {
            *minor_status = code;
            k5_mutex_unlock(&kname->lock);
            krb5_free_context(context);
            return GSS_S_UNAVAILABLE;
        }
    }

    kmodule = (char *)type_id->value;
    if (kmodule[type_id->length] != '\0') {
        k5_mutex_unlock(&kname->lock);
        krb5_free_context(context);
        return GSS_S_UNAVAILABLE;
    }

    code = krb5_authdata_export_internal(context,
                                         kname->ad_context,
                                         authenticated,
                                         kmodule,
                                         (void **)output);

    k5_mutex_unlock(&kname->lock);
    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}
Exemple #11
0
OM_uint32
krb5_gss_get_name_attribute(OM_uint32 *minor_status,
                            gss_name_t name,
                            gss_buffer_t attr,
                            int *authenticated,
                            int *complete,
                            gss_buffer_t value,
                            gss_buffer_t display_value,
                            int *more)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    krb5_data kattr;
    krb5_boolean kauthenticated;
    krb5_boolean kcomplete;
    krb5_data kvalue;
    krb5_data kdisplay_value;

    if (minor_status != NULL)
        *minor_status = 0;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    if (!kg_validate_name(name)) {
        *minor_status = (OM_uint32)G_VALIDATE_FAILED;
        krb5_free_context(context);
        return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        krb5_free_context(context);
        return GSS_S_FAILURE;
    }

    if (kname->ad_context == NULL) {
        code = krb5_authdata_context_init(context, &kname->ad_context);
        if (code != 0) {
            *minor_status = code;
            k5_mutex_unlock(&kname->lock);
            krb5_free_context(context);
            return GSS_S_UNAVAILABLE;
        }
    }

    kattr.data = (char *)attr->value;
    kattr.length = attr->length;

    kauthenticated = FALSE;
    kcomplete = FALSE;

    code = krb5_authdata_get_attribute(context,
                                       kname->ad_context,
                                       &kattr,
                                       &kauthenticated,
                                       &kcomplete,
                                       value ? &kvalue : NULL,
                                       display_value ? &kdisplay_value : NULL,
                                       more);
    if (code == 0) {
        if (value != NULL) {
            value->value = kvalue.data;
            value->length = kvalue.length;
        }

        if (authenticated != NULL)
            *authenticated = kauthenticated;
        if (complete != NULL)
            *complete = kcomplete;

        if (display_value != NULL) {
            display_value->value = kdisplay_value.data;
            display_value->length = kdisplay_value.length;
        }
    }

    k5_mutex_unlock(&kname->lock);
    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}