Beispiel #1
0
/*
 * Check whether the request satisfies the conditions for generating a referral
 * TGT.  The caller checks whether the hostname component looks like a FQDN.
 */
static krb5_boolean
is_referral_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request)
{
    krb5_boolean ret = FALSE;
    char *stype = NULL;
    char *ref_services = kdc_active_realm->realm_host_based_services;
    char *nonref_services = kdc_active_realm->realm_no_host_referral;

    if (!(request->kdc_options & KDC_OPT_CANONICALIZE))
        return FALSE;

    if (request->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY)
        return FALSE;

    if (krb5_princ_size(kdc_context, request->server) != 2)
        return FALSE;

    stype = data2string(krb5_princ_component(kdc_context, request->server, 0));
    if (stype == NULL)
        return FALSE;
    switch (krb5_princ_type(kdc_context, request->server)) {
    case KRB5_NT_UNKNOWN:
        /* Allow referrals for NT-UNKNOWN principals, if configured. */
        if (kdc_active_realm->realm_host_based_services != NULL) {
            if (!krb5_match_config_pattern(ref_services, stype) &&
                !krb5_match_config_pattern(ref_services, KRB5_CONF_ASTERISK))
                goto cleanup;
        } else
            goto cleanup;
        /* FALLTHROUGH */
    case KRB5_NT_SRV_HST:
    case KRB5_NT_SRV_INST:
        /* Deny referrals for specific service types, if configured. */
        if (kdc_active_realm->realm_no_host_referral != NULL) {
            if (krb5_match_config_pattern(nonref_services, stype))
                goto cleanup;
            if (krb5_match_config_pattern(nonref_services, KRB5_CONF_ASTERISK))
                goto cleanup;
        }
        ret = TRUE;
        break;
    default:
        goto cleanup;
    }
cleanup:
    free(stype);
    return ret;
}
Beispiel #2
0
static krb5_int32
prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ)
{
    krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH;
    size_t len = 0;
    char **realms, **cpp, *temp_buf=NULL;
    krb5_data *comp1 = NULL, *comp2 = NULL;
    char *comp1_str = NULL;

    /* By now we know that server principal name is unknown.
     * If CANONICALIZE flag is set in the request
     * If req is not U2U authn. req
     * the requested server princ. has exactly two components
     * either
     *      the name type is NT-SRV-HST
     *      or name type is NT-UNKNOWN and
     *         the 1st component is listed in conf file under host_based_services
     * the 1st component is not in a list in conf under "no_host_referral"
     * the 2d component looks like fully-qualified domain name (FQDN)
     * If all of these conditions are satisfied - try mapping the FQDN and
     * re-process the request as if client had asked for cross-realm TGT.
     */
    if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) &&
        !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) &&
        krb5_princ_size(kdc_context, request->server) == 2) {

        comp1 = krb5_princ_component(kdc_context, request->server, 0);
        comp2 = krb5_princ_component(kdc_context, request->server, 1);

        comp1_str = calloc(1,comp1->length+1);
        if (!comp1_str) {
            retval = ENOMEM;
            goto cleanup;
         }
        strlcpy(comp1_str,comp1->data,comp1->length+1);

        if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST ||
            (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN &&
            kdc_active_realm->realm_host_based_services != NULL &&
            (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE ||
             krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE))) &&
            (kdc_active_realm->realm_no_host_referral == NULL ||
            (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, KRB5_CONF_ASTERISK) == FALSE &&
             krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) {

            for (len=0; len < comp2->length; len++) {
                 if (comp2->data[len] == '.') break;
            }
            if (len == comp2->length)
                goto cleanup;
            temp_buf = calloc(1, comp2->length+1);
            if (!temp_buf){
                retval = ENOMEM;
                goto cleanup;
            }
            strlcpy(temp_buf, comp2->data,comp2->length+1);
            retval = krb5int_get_domain_realm_mapping(kdc_context, temp_buf, &realms);
            free(temp_buf);
            if (retval) {
                /* no match found */
                kdc_err(kdc_context, retval, 0);
                goto cleanup;
            }
            if (realms == 0) {
                retval = KRB5KRB_AP_ERR_BADMATCH;
                goto cleanup;
            }
            if (realms[0] == 0) {
                free(realms);
                retval = KRB5KRB_AP_ERR_BADMATCH;
                goto cleanup;
            }
            /* Modify request.
             * Construct cross-realm tgt :  krbtgt/REMOTE_REALM@LOCAL_REALM
             * and use it as a principal in this req.
             */
            retval = krb5_build_principal(kdc_context, krbtgt_princ,
                                          (*request->server).realm.length,
                                          (*request->server).realm.data,
                                          "krbtgt", realms[0], (char *)0);
            for (cpp = realms; *cpp; cpp++)
                   free(*cpp);
        }
    }
cleanup:
    free(comp1_str);
    return retval;
}
Beispiel #3
0
static void
initialize_realms(krb5_context kcontext, int argc, char **argv)
{
    int                 c;
    char                *db_name = (char *) NULL;
    char                *lrealm = (char *) NULL;
    char                *mkey_name = (char *) NULL;
    krb5_error_code     retval;
    krb5_enctype        menctype = ENCTYPE_UNKNOWN;
    kdc_realm_t         *rdatap = NULL;
    krb5_boolean        manual = FALSE;
    krb5_boolean        def_restrict_anon;
    char                *default_udp_ports = 0;
    char                *default_tcp_ports = 0;
    krb5_pointer        aprof;
    const char          *hierarchy[3];
    char                *no_refrls = NULL;
    char                *host_based_srvcs = NULL;
    int                  db_args_size = 0;
    char                **db_args = NULL;

    extern char *optarg;

    if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) {
        hierarchy[0] = KRB5_CONF_KDCDEFAULTS;
        hierarchy[1] = KRB5_CONF_KDC_PORTS;
        hierarchy[2] = (char *) NULL;
        if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports))
            default_udp_ports = 0;
        hierarchy[1] = KRB5_CONF_KDC_TCP_PORTS;
        if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports))
            default_tcp_ports = 0;
        hierarchy[1] = KRB5_CONF_MAX_DGRAM_REPLY_SIZE;
        if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size))
            max_dgram_reply_size = MAX_DGRAM_SIZE;
        hierarchy[1] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT;
        if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &def_restrict_anon))
            def_restrict_anon = FALSE;
        hierarchy[1] = KRB5_CONF_NO_HOST_REFERRAL;
        if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls))
            no_refrls = 0;
        if (!no_refrls ||
            krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) {
            hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES;
            if (krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs))
                host_based_srvcs = 0;
        }

        krb5_aprof_finish(aprof);
    }

    if (default_udp_ports == 0) {
        default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST);
        if (default_udp_ports == 0) {
            fprintf(stderr, _(" KDC cannot initialize. Not enough memory\n"));
            exit(1);
        }
    }
    if (default_tcp_ports == 0) {
        default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST);
        if (default_tcp_ports == 0) {
            fprintf(stderr, _(" KDC cannot initialize. Not enough memory\n"));
            exit(1);
        }
    }

    /*
     * Loop through the option list.  Each time we encounter a realm name,
     * use the previously scanned options to fill in for defaults.
     */
    while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:P:p:s:nw:4:X3")) != -1) {
        switch(c) {
        case 'x':
            db_args_size++;
            {
                char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
                if( temp == NULL )
                {
                    fprintf(stderr, _("%s: KDC cannot initialize. Not enough "
                                      "memory\n"), argv[0]);
                    exit(1);
                }

                db_args = temp;
            }
            db_args[db_args_size-1] = optarg;
            db_args[db_args_size]   = NULL;
            break;

        case 'r':                       /* realm name for db */
            if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) {
                if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
                    if ((retval = init_realm(rdatap, optarg, mkey_name,
                                             menctype, default_udp_ports,
                                             default_tcp_ports, manual,
                                             def_restrict_anon, db_args,
                                             no_refrls, host_based_srvcs))) {
                        fprintf(stderr, _("%s: cannot initialize realm %s - "
                                          "see log file for details\n"),
                                argv[0], optarg);
                        exit(1);
                    }
                    kdc_realmlist[kdc_numrealms] = rdatap;
                    kdc_numrealms++;
                    free(db_args), db_args=NULL, db_args_size = 0;
                }
                else
                {
                    fprintf(stderr, _("%s: cannot initialize realm %s. Not "
                                      "enough memory\n"), argv[0], optarg);
                    exit(1);
                }
            }
            break;
        case 'd':                       /* pathname for db */
            /* now db_name is not a seperate argument.
             * It has to be passed as part of the db_args
             */
            if( db_name == NULL ) {
                if (asprintf(&db_name, "dbname=%s", optarg) < 0) {
                    fprintf(stderr, _("%s: KDC cannot initialize. Not enough "
                                      "memory\n"), argv[0]);
                    exit(1);
                }
            }

            db_args_size++;
            {
                char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
                if( temp == NULL )
                {
                    fprintf(stderr, _("%s: KDC cannot initialize. Not enough "
                                      "memory\n"), argv[0]);
                    exit(1);
                }

                db_args = temp;
            }
            db_args[db_args_size-1] = db_name;
            db_args[db_args_size]   = NULL;
            break;
        case 'm':                       /* manual type-in of master key */
            manual = TRUE;
            if (menctype == ENCTYPE_UNKNOWN)
                menctype = ENCTYPE_DES_CBC_CRC;
            break;
        case 'M':                       /* master key name in DB */
            mkey_name = optarg;
            break;
        case 'n':
            nofork++;                   /* don't detach from terminal */
            break;
        case 'w':                       /* create multiple worker processes */
            workers = atoi(optarg);
            if (workers <= 0)
                usage(argv[0]);
            break;
        case 'k':                       /* enctype for master key */
            if (krb5_string_to_enctype(optarg, &menctype))
                com_err(argv[0], 0, _("invalid enctype %s"), optarg);
            break;
        case 'R':
            /* Replay cache name; defunct since we don't use a replay cache. */
            break;
        case 'P':
            pid_file = optarg;
            break;
        case 'p':
            if (default_udp_ports)
                free(default_udp_ports);
            default_udp_ports = strdup(optarg);
            if (!default_udp_ports) {
                fprintf(stderr, _(" KDC cannot initialize. Not enough "
                                  "memory\n"));
                exit(1);
            }
#if 0 /* not yet */
            if (default_tcp_ports)
                free(default_tcp_ports);
            default_tcp_ports = strdup(optarg);
#endif
            break;
        case '4':
            break;
        case 'X':
            break;
        case '?':
        default:
            usage(argv[0]);
        }
    }

    /*
     * Check to see if we processed any realms.
     */
    if (kdc_numrealms == 0) {
        /* no realm specified, use default realm */
        if ((retval = krb5_get_default_realm(kcontext, &lrealm))) {
            com_err(argv[0], retval,
                    _("while attempting to retrieve default realm"));
            fprintf (stderr,
                     _("%s: %s, attempting to retrieve default realm\n"),
                     argv[0], krb5_get_error_message(kcontext, retval));
            exit(1);
        }
        if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) {
            if ((retval = init_realm(rdatap, lrealm, mkey_name, menctype,
                                     default_udp_ports, default_tcp_ports,
                                     manual, def_restrict_anon, db_args,
                                     no_refrls, host_based_srvcs))) {
                fprintf(stderr, _("%s: cannot initialize realm %s - see log "
                                  "file for details\n"), argv[0], lrealm);
                exit(1);
            }
            kdc_realmlist[0] = rdatap;
            kdc_numrealms++;
        }
        krb5_free_default_realm(kcontext, lrealm);
    }

    /* Ensure that this is set for our first request. */
    kdc_active_realm = kdc_realmlist[0];
    if (default_udp_ports)
        free(default_udp_ports);
    if (default_tcp_ports)
        free(default_tcp_ports);
    if (db_args)
        free(db_args);
    if (db_name)
        free(db_name);
    if (host_based_srvcs)
        free(host_based_srvcs);
    if (no_refrls)
        free(no_refrls);

    return;
}
Beispiel #4
0
static krb5_error_code
handle_referral_params(krb5_realm_params *rparams,
                       char *no_refrls, char *host_based_srvcs,
                       kdc_realm_t *rdp )
{
    krb5_error_code retval = 0;
    if (no_refrls && krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == TRUE) {
        rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK);
        if (!rdp->realm_no_host_referral)
            retval = ENOMEM;
    } else {
        if (rparams && rparams->realm_no_host_referral) {
            if (krb5_match_config_pattern(rparams->realm_no_host_referral,
                                          KRB5_CONF_ASTERISK) == TRUE) {
                rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK);
                if (!rdp->realm_no_host_referral)
                    retval = ENOMEM;
            } else if  (no_refrls && (asprintf(&(rdp->realm_no_host_referral),
                                               "%s%s%s%s%s", " ", no_refrls," ",
                                               rparams->realm_no_host_referral, " ") < 0))
                retval = ENOMEM;
            else if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ",
                              rparams->realm_no_host_referral, " ") < 0)
                retval = ENOMEM;
        } else if( no_refrls != NULL) {
            if ( asprintf(&(rdp->realm_no_host_referral),
                          "%s%s%s", " ", no_refrls, " ") < 0)
                retval = ENOMEM;
        } else
            rdp->realm_no_host_referral = NULL;
    }

    if (rdp->realm_no_host_referral &&
        krb5_match_config_pattern(rdp->realm_no_host_referral,
                                  KRB5_CONF_ASTERISK) == TRUE) {
        rdp->realm_host_based_services = NULL;
        return 0;
    }

    if (host_based_srvcs &&
        (krb5_match_config_pattern(host_based_srvcs, KRB5_CONF_ASTERISK) == TRUE)) {
        rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK);
        if (!rdp->realm_host_based_services)
            retval = ENOMEM;
    } else {
        if (rparams && rparams->realm_host_based_services) {
            if (krb5_match_config_pattern(rparams->realm_host_based_services,
                                          KRB5_CONF_ASTERISK) == TRUE) {
                rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK);
                if (!rdp->realm_host_based_services)
                    retval = ENOMEM;
            } else if (host_based_srvcs) {
                if (asprintf(&(rdp->realm_host_based_services), "%s%s%s%s%s",
                             " ", host_based_srvcs," ",
                             rparams->realm_host_based_services, " ") < 0)
                    retval = ENOMEM;
            } else if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ",
                                rparams->realm_host_based_services, " ") < 0)
                retval = ENOMEM;
        } else if (host_based_srvcs) {
            if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ",
                         host_based_srvcs, " ") < 0)
                retval = ENOMEM;
        } else
            rdp->realm_host_based_services = NULL;
    }

    return retval;
}