Skip to content

HTTP challenge with DNS fallback #100

Description

@oalders

In dealing with wildcard domains, it's handy to do the HTTP challenges first and then fall back to DNS for any names (ie wildcards) which failed the HTTP challenge. I could not find a way to do this with the current API, so I have been doing the following. I realize that this is bad for poking at the internals, but as a stopgap it does the trick. Am I missing something?

Please note: I can't really take credit for this. It was quite late at night and I had claude.ai generate most of it in order to rest my brain.

package Crypt::LE::Batch;

use strict;
use warnings;

use parent 'Crypt::LE';

use Crypt::LE qw( OK );

sub accept_challenge {
    my ( $self, $cb, $params, $type ) = @_;

    # For non-dns challenges, use parent behavior
    return $self->SUPER::accept_challenge( $cb, $params, $type )
        unless $type eq 'dns';

    # Store original state
    my $full_challenges        = $self->{challenges};
    my $full_domains           = $self->{loaded_domains};
    my $full_active_challenges = $self->{active_challenges};

    # Filter to only keep wildcard domains
    my $wildcard_challenges = {};
    my @wildcard_domains;
    foreach my $domain (@$full_domains) {
        next unless $domain =~ /^\*\./;    # only wildcards
        if ( exists $full_challenges->{$domain} ) {
            $wildcard_challenges->{$domain} = $full_challenges->{$domain};
            push @wildcard_domains, $domain;
        }
    }

    # Temporarily replace with filtered set
    $self->{challenges}        = $wildcard_challenges;
    $self->{loaded_domains}    = \@wildcard_domains;
    $self->{active_challenges} = {};    # Start fresh for DNS challenges

    # Let parent handle the actual validation with filtered domains
    my $status = $self->SUPER::accept_challenge( $cb, $params, $type );

    if ( $status == OK ) {

        # Merge the active challenges back
        $self->{active_challenges} = {
            %{ $full_active_challenges || {} },
            %{ $self->{active_challenges} || {} }
        };
    }

    # Restore remaining original state
    $self->{challenges}     = $full_challenges;
    $self->{loaded_domains} = $full_domains;

    return $status;
}

# Override verify_challenge to only verify wildcards for DNS
sub verify_challenge {
    my ( $self, $cb, $params, $type ) = @_;

    return $self->SUPER::verify_challenge( $cb, $params, $type )
        unless $type && $type eq 'dns';

    # Store original state
    my $full_domains = $self->{loaded_domains};

    # Filter to only verify wildcard domains
    my @wildcard_domains = grep { /^\*\./ } @$full_domains;
    $self->{loaded_domains} = \@wildcard_domains;

    # Let parent handle verification
    my $status = $self->SUPER::verify_challenge( $cb, $params, $type );

    # Restore original state
    $self->{loaded_domains} = $full_domains;

    return $status;
}

1;

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions