@@ -3189,7 +3189,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
31893189 type = response_type_from_server (
31903190 (int )((iq -> chase_flags & BIT_RD ) || iq -> chase_to_rd ),
31913191 iq -> response , & iq -> qinfo_out , iq -> dp , & iq -> empty_nodata_found ,
3192- iq -> msg_lame_empty , iq -> msg_lame_referral );
3192+ iq -> msg_lame_empty , iq -> msg_lame_referral , qstate -> env -> cfg );
31933193 iq -> chase_to_rd = 0 ;
31943194 /* remove TC flag, if this is erroneously set by TCP upstream */
31953195 iq -> response -> rep -> flags &= ~BIT_TC ;
@@ -3302,6 +3302,47 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
33023302 * to send another query with a new qtype. */
33033303 type = RESPONSE_TYPE_ANSWER ;
33043304 }
3305+ if (type == RESPONSE_TYPE_ANSWER &&
3306+ !qstate -> env -> cfg -> harden_cname_follow /* cname chain from upstream is allowed */ &&
3307+ qstate -> env -> auth_zones &&
3308+ /* Check for CNAMEs in answer and RPZ after the CNAME. */
3309+ reply_find_rrset_section_an (
3310+ iq -> response -> rep , iq -> qchase .qname ,
3311+ iq -> qchase .qname_len , LDNS_RR_TYPE_CNAME ,
3312+ iq -> qchase .qclass ) != NULL ) {
3313+ /* If this is an answer with CNAMEs in front, and
3314+ * RPZ wants to modify after CNAME(s), cut off, the
3315+ * remainder, and treat as the CNAME response */
3316+ size_t i ;
3317+ uint8_t * origname = iq -> qchase .qname ;
3318+ size_t orignamelen = iq -> qchase .qname_len ;
3319+ for (i = 0 ; i < iq -> response -> rep -> an_numrrsets ; i ++ ) {
3320+ struct dns_msg * forged_response ;
3321+ if (ntohs (iq -> response -> rep -> rrsets [i ]-> rk .type ) ==
3322+ LDNS_RR_TYPE_DNAME ) {
3323+ continue ;
3324+ }
3325+ if (ntohs (iq -> response -> rep -> rrsets [i ]-> rk .type ) !=
3326+ LDNS_RR_TYPE_CNAME ) {
3327+ break ;
3328+ }
3329+ get_cname_target (iq -> response -> rep -> rrsets [i ],
3330+ & iq -> qchase .qname , & iq -> qchase .qname_len );
3331+ forged_response = rpz_callback_from_iterator_cname (qstate , iq );
3332+ if (forged_response ) {
3333+ /* Cut off the answer section at this point.
3334+ * RPZ is going to make an answer, in the
3335+ * processInit after the CNAME(s) in front
3336+ * are handled. */
3337+ shorten_answer_cname (iq -> response -> rep ,
3338+ iq -> qchase .qname );
3339+ type = RESPONSE_TYPE_CNAME ;
3340+ break ;
3341+ }
3342+ }
3343+ iq -> qchase .qname = origname ;
3344+ iq -> qchase .qname_len = orignamelen ;
3345+ }
33053346
33063347 /* handle each of the type cases */
33073348 if (type == RESPONSE_TYPE_ANSWER ) {
@@ -3804,7 +3845,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
38043845 type = response_type_from_server (
38053846 (int )((iq -> chase_flags & BIT_RD ) || iq -> chase_to_rd ),
38063847 iq -> response , & iq -> qchase , iq -> dp , NULL , iq -> msg_lame_empty ,
3807- iq -> msg_lame_referral );
3848+ iq -> msg_lame_referral , qstate -> env -> cfg );
38083849 if (type == RESPONSE_TYPE_ANSWER ) {
38093850 qstate -> return_rcode = LDNS_RCODE_NOERROR ;
38103851 qstate -> return_msg = iq -> response ;
0 commit comments