/* * 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; }
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; }
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; }
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; }