示例#1
0
文件: t_std_conf.c 项目: WeiY/krb5
static void
test_locate_kdc(krb5_context ctx, char *realm)
{
    struct serverlist servers;
    size_t i;
    int get_masters = FALSE;
    krb5_data rlm;
    krb5_error_code retval;

    rlm.data = realm;
    rlm.length = strlen(realm);
    retval = k5_locate_kdc(ctx, &rlm, &servers, get_masters, 0);
    if (retval) {
        com_err("krb5_locate_kdc", retval, 0);
        return;
    }
    printf("krb_locate_kdc(%s) returned:", realm);
    for (i = 0; i < servers.nservers; i++) {
        struct server_entry *entry = &servers.servers[i];
        if (entry->hostname) {
            printf(" host:%s/%d", entry->hostname, ntohs(entry->port));
            continue;
        }
        switch (entry->family) {
        case AF_INET:
        {
            struct sockaddr_in *s_sin = (struct sockaddr_in *)&entry->addr;
            printf(" inet:%s/%d", inet_ntoa(s_sin->sin_addr),
                   ntohs(s_sin->sin_port));
        }
        break;
        case AF_INET6:
        {
            struct sockaddr_in6 *s_sin6 = (struct sockaddr_in6 *)&entry->addr;
            int j;
            printf(" inet6");
            for (j = 0; j < 8; j++)
                printf(":%x",
                       (s_sin6->sin6_addr.s6_addr[2*j] * 256
                        + s_sin6->sin6_addr.s6_addr[2*j+1]));
            printf("/%d", ntohs(s_sin6->sin6_port));
            break;
        }
        default:
            printf(" unknown-af-%d", entry->family);
            break;
        }
    }
    k5_free_serverlist(&servers);
    printf("\n");
}
示例#2
0
krb5_error_code
krb5_sendto_kdc(krb5_context context, const krb5_data *message,
                const krb5_data *realm, krb5_data *reply, int *use_master,
                int no_udp)
{
    krb5_error_code retval, err;
    struct serverlist servers;
    int server_used;
    k5_transport_strategy strategy;

    /*
     * find KDC location(s) for realm
     */

    /*
     * BUG: This code won't return "interesting" errors (e.g., out of mem,
     * bad config file) from locate_kdc.  KRB5_REALM_CANT_RESOLVE can be
     * ignored from one query of two, but if only one query is done, or
     * both return that error, it should be returned to the caller.  Also,
     * "interesting" errors (not KRB5_KDC_UNREACH) from sendto_{udp,tcp}
     * should probably be returned as well.
     */

    TRACE_SENDTO_KDC(context, message->length, realm, *use_master, no_udp);

    if (!no_udp && context->udp_pref_limit < 0) {
        int tmp;
        retval = profile_get_integer(context->profile,
                                     KRB5_CONF_LIBDEFAULTS, KRB5_CONF_UDP_PREFERENCE_LIMIT, 0,
                                     DEFAULT_UDP_PREF_LIMIT, &tmp);
        if (retval)
            return retval;
        if (tmp < 0)
            tmp = DEFAULT_UDP_PREF_LIMIT;
        else if (tmp > HARD_UDP_LIMIT)
            /* In the unlikely case that a *really* big value is
               given, let 'em use as big as we think we can
               support.  */
            tmp = HARD_UDP_LIMIT;
        context->udp_pref_limit = tmp;
    }

    if (no_udp)
        strategy = NO_UDP;
    else if (message->length <= (unsigned int) context->udp_pref_limit)
        strategy = UDP_FIRST;
    else
        strategy = UDP_LAST;

    retval = k5_locate_kdc(context, realm, &servers, *use_master, no_udp);
    if (retval)
        return retval;

    err = 0;
    retval = k5_sendto(context, message, realm, &servers, strategy, NULL,
                       reply, NULL, NULL, &server_used,
                       check_for_svc_unavailable, &err);
    if (retval == KRB5_KDC_UNREACH) {
        if (err == KDC_ERR_SVC_UNAVAILABLE) {
            retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
        } else {
            k5_setmsg(context, retval,
                      _("Cannot contact any KDC for realm '%.*s'"),
                      realm->length, realm->data);
        }
    }
    if (retval)
        goto cleanup;

    /* Set use_master to 1 if we ended up talking to a master when we didn't
     * explicitly request to. */
    if (*use_master == 0) {
        *use_master = k5_kdc_is_master(context, realm,
                                       &servers.servers[server_used]);
        TRACE_SENDTO_KDC_MASTER(context, *use_master);
    }

cleanup:
    k5_free_serverlist(&servers);
    return retval;
}
示例#3
0
int
main (int argc, char *argv[])
{
    char *p, *realmname;
    krb5_data realm;
    krb5_context ctx;
    krb5_error_code err;
    int master = 0;

    p = strrchr (argv[0], '/');
    if (p)
        prog = p+1;
    else
        prog = argv[0];

    switch (argc) {
    case 2:
        /* foo $realm */
        realmname = argv[1];
        break;
    case 3:
        if (!strcmp (argv[1], "-c"))
            how = LOOKUP_CONF;
        else if (!strcmp (argv[1], "-d"))
            how = LOOKUP_DNS;
        else if (!strcmp (argv[1], "-m"))
            master = 1;
        else
            goto usage;
        realmname = argv[2];
        break;
    default:
    usage:
        fprintf (stderr, "%s: usage: %s [-c | -d | -m] realm\n", prog, prog);
        return 1;
    }

    err = krb5_init_context (&ctx);
    if (err)
        kfatal (err);

    realm.data = realmname;
    realm.length = strlen (realmname);

    switch (how) {
    case LOOKUP_CONF:
        err = krb5_locate_srv_conf(ctx, &realm, "kdc", &sl, htons(88));
        break;

    case LOOKUP_DNS:
        err = locate_srv_dns_1(&realm, "_kerberos", "_udp", &sl);
        break;

    case LOOKUP_WHATEVER:
        err = k5_locate_kdc(ctx, &realm, &sl, master, FALSE);
        break;
    }
    if (err) kfatal (err);
    print_addrs();

    k5_free_serverlist(&sl);
    krb5_free_context(ctx);
    return 0;
}
示例#4
0
krb5_error_code
krb5_sendto_kdc(krb5_context context, const krb5_data *message,
                const krb5_data *realm, krb5_data *reply, int *use_master,
                int tcp_only)
{
    krb5_error_code retval, err;
    struct serverlist servers;
    int socktype1 = 0, socktype2 = 0, server_used;

    /*
     * find KDC location(s) for realm
     */

    /*
     * BUG: This code won't return "interesting" errors (e.g., out of mem,
     * bad config file) from locate_kdc.  KRB5_REALM_CANT_RESOLVE can be
     * ignored from one query of two, but if only one query is done, or
     * both return that error, it should be returned to the caller.  Also,
     * "interesting" errors (not KRB5_KDC_UNREACH) from sendto_{udp,tcp}
     * should probably be returned as well.
     */

    dprint("krb5_sendto_kdc(%d@%p, \"%D\", use_master=%d, tcp_only=%d)\n",
           message->length, message->data, realm, *use_master, tcp_only);
    TRACE_SENDTO_KDC(context, message->length, realm, *use_master, tcp_only);

    if (!tcp_only && context->udp_pref_limit < 0) {
        int tmp;
        retval = profile_get_integer(context->profile,
                                     KRB5_CONF_LIBDEFAULTS, KRB5_CONF_UDP_PREFERENCE_LIMIT, 0,
                                     DEFAULT_UDP_PREF_LIMIT, &tmp);
        if (retval)
            return retval;
        if (tmp < 0)
            tmp = DEFAULT_UDP_PREF_LIMIT;
        else if (tmp > HARD_UDP_LIMIT)
            /* In the unlikely case that a *really* big value is
               given, let 'em use as big as we think we can
               support.  */
            tmp = HARD_UDP_LIMIT;
        context->udp_pref_limit = tmp;
    }

    if (tcp_only)
        socktype1 = SOCK_STREAM, socktype2 = 0;
    else if (message->length <= (unsigned int) context->udp_pref_limit)
        socktype1 = SOCK_DGRAM, socktype2 = SOCK_STREAM;
    else
        socktype1 = SOCK_STREAM, socktype2 = SOCK_DGRAM;

    retval = k5_locate_kdc(context, realm, &servers, *use_master,
                           tcp_only ? SOCK_STREAM : 0);
    if (retval)
        return retval;

    retval = k5_sendto(context, message, &servers, socktype1, socktype2,
                       NULL, reply, NULL, NULL, &server_used,
                       check_for_svc_unavailable, &err);
    if (retval == KRB5_KDC_UNREACH) {
        if (err == KDC_ERR_SVC_UNAVAILABLE) {
            retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
        } else {
            krb5_set_error_message(context, retval,
                                   "Cannot contact any KDC for realm '%.*s'",
                                   realm->length, realm->data);
        }
    }
    if (retval)
        goto cleanup;

    /* Set use_master to 1 if we ended up talking to a master when we didn't
     * explicitly request to. */
    if (*use_master == 0) {
        struct serverlist mservers;
        struct server_entry *entry = &servers.servers[server_used];
        retval = k5_locate_kdc(context, realm, &mservers, TRUE,
                               entry->socktype);
        if (retval == 0) {
            if (in_addrlist(entry, &mservers))
                *use_master = 1;
            k5_free_serverlist(&mservers);
        }
        TRACE_SENDTO_KDC_MASTER(context, *use_master);
        retval = 0;
    }

cleanup:
    k5_free_serverlist(&servers);
    return retval;
}