static krb5_error_code check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) { char **realms; int num_realms; krb5_error_code ret; if(enc->transited.tr_type != DOMAIN_X500_COMPRESS) return KRB5KDC_ERR_TRTYPE_NOSUPP; if(enc->transited.contents.length == 0) return 0; ret = krb5_domain_x500_decode(context, enc->transited.contents, &realms, &num_realms, enc->crealm, ticket->realm); if(ret) return ret; ret = krb5_check_transited(context, enc->crealm, ticket->realm, realms, num_realms, NULL); free(realms); return ret; }
static krb5_error_code check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) { char **realms; unsigned int num_realms, n; krb5_error_code ret; /* * Windows 2000 and 2003 uses this inside their TGT so it's normaly * not seen by others, however, samba4 joined with a Windows AD as * a Domain Controller gets exposed to this. */ if(enc->transited.tr_type == 0 && enc->transited.contents.length == 0) return 0; if(enc->transited.tr_type != DOMAIN_X500_COMPRESS) return KRB5KDC_ERR_TRTYPE_NOSUPP; if(enc->transited.contents.length == 0) return 0; ret = krb5_domain_x500_decode(context, enc->transited.contents, &realms, &num_realms, enc->crealm, ticket->realm); if(ret) return ret; ret = krb5_check_transited(context, enc->crealm, ticket->realm, realms, num_realms, NULL); for (n = 0; n < num_realms; n++) free(realms[n]); free(realms); return ret; }
static void check_linear(krb5_context context, const char *client_realm, const char *server_realm, const char *realm, ...) { unsigned int num_inrealms = 0, num_realms = 0, n; char **inrealms = NULL; char **realms = NULL; krb5_error_code ret; krb5_data tr; va_list va; krb5_data_zero(&tr); va_start(va, realm); while (realm) { inrealms = erealloc(inrealms, (num_inrealms + 2) * sizeof(inrealms[0])); inrealms[num_inrealms] = rk_UNCONST(realm); num_inrealms++; realm = va_arg(va, const char *); } if (inrealms) inrealms[num_inrealms] = NULL; ret = krb5_domain_x500_encode(inrealms, num_inrealms, &tr); if (ret) krb5_err(context, 1, ret, "krb5_domain_x500_encode"); ret = krb5_domain_x500_decode(context, tr, &realms, &num_realms, client_realm, server_realm); if (ret) krb5_err(context, 1, ret, "krb5_domain_x500_decode"); krb5_data_free(&tr); if (num_inrealms != num_realms) errx(1, "num_inrealms != num_realms"); for(n = 0; n < num_realms; n++) free(realms[n]); free(realms); free(inrealms); }
static krb5_error_code fix_transited_encoding(krb5_context context, krb5_kdc_configuration *config, krb5_boolean check_policy, const TransitedEncoding *tr, EncTicketPart *et, const char *client_realm, const char *server_realm, const char *tgt_realm) { krb5_error_code ret = 0; char **realms, **tmp; int num_realms; int i; switch (tr->tr_type) { case DOMAIN_X500_COMPRESS: break; case 0: /* * Allow empty content of type 0 because that is was Microsoft * generates in their TGT. */ if (tr->contents.length == 0) break; kdc_log(context, config, 0, "Transited type 0 with non empty content"); return KRB5KDC_ERR_TRTYPE_NOSUPP; default: kdc_log(context, config, 0, "Unknown transited type: %u", tr->tr_type); return KRB5KDC_ERR_TRTYPE_NOSUPP; } ret = krb5_domain_x500_decode(context, tr->contents, &realms, &num_realms, client_realm, server_realm); if(ret){ krb5_warn(context, ret, "Decoding transited encoding"); return ret; } if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { /* not us, so add the previous realm to transited set */ if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) { ret = ERANGE; goto free_realms; } tmp = realloc(realms, (num_realms + 1) * sizeof(*realms)); if(tmp == NULL){ ret = ENOMEM; goto free_realms; } realms = tmp; realms[num_realms] = strdup(tgt_realm); if(realms[num_realms] == NULL){ ret = ENOMEM; goto free_realms; } num_realms++; } if(num_realms == 0) { if(strcmp(client_realm, server_realm)) kdc_log(context, config, 0, "cross-realm %s -> %s", client_realm, server_realm); } else { size_t l = 0; char *rs; for(i = 0; i < num_realms; i++) l += strlen(realms[i]) + 2; rs = malloc(l); if(rs != NULL) { *rs = '\0'; for(i = 0; i < num_realms; i++) { if(i > 0) strlcat(rs, ", ", l); strlcat(rs, realms[i], l); } kdc_log(context, config, 0, "cross-realm %s -> %s via [%s]", client_realm, server_realm, rs); free(rs); } } if(check_policy) { ret = krb5_check_transited(context, client_realm, server_realm, realms, num_realms, NULL); if(ret) { krb5_warn(context, ret, "cross-realm %s -> %s", client_realm, server_realm); goto free_realms; } et->flags.transited_policy_checked = 1; } et->transited.tr_type = DOMAIN_X500_COMPRESS; ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents); if(ret) krb5_warn(context, ret, "Encoding transited encoding"); free_realms: for(i = 0; i < num_realms; i++) free(realms[i]); free(realms); return ret; }