File: dnsval.py

package info (click to toggle)
dnssec-tools 1.13-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 16,064 kB
  • sloc: perl: 44,399; ansic: 31,547; cpp: 21,306; sh: 15,813; xml: 2,113; makefile: 1,390; pascal: 836; python: 290; csh: 11
file content (316 lines) | stat: -rwxr-xr-x 11,568 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# #######################################################################
# Copyright (c) 2012, Bob Novas, Shinkuro, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions 
# are met:
#
#  - Redistributions of source code must retain the above copyright  
#    notice, this list of conditions and the following disclaimer.
#
#  - Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in the 
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #######################################################################

""" 
dnsval.py - wraps the dnssec-tools libval-threads library.
see http://dnssec-tools.org

$Id: dnsval.py 76 2012-02-15 20:51:03Z bob.novas $
"""


from ctypes import CDLL, POINTER, RTLD_GLOBAL, Structure
from ctypes import c_char_p, c_int, c_long, c_ubyte, c_uint, c_ulong, c_void_p
from ctypes import byref, cast, create_string_buffer, pointer, sizeof
from ctypes import  c_int8,  c_int16,  c_int32,  c_int64
from ctypes import c_uint8, c_uint16, c_uint32, c_uint64

import os
import sys

# validator flags
VAL_QUERY_AC_DETAIL         = 0x00000001
VAL_QUERY_DONT_VALIDATE     = 0x00000002
VAL_QUERY_NO_DLV            = 0x00000004
VAL_QUERY_USING_DLV         = 0x00000008
VAL_QUERY_ASYNC             = 0x00000010
VAL_QUERY_NO_EDNS0_FALLBACK = 0x00000020
VAL_QUERY_SKIP_RESOLVER     = 0x00000040
VAL_QUERY_MARK_FOR_DELETION = 0x00000080
VAL_QUERY_IGNORE_SKEW       = 0x00000100
VAL_QUERY_RECURSE           = 0x00010000
VAL_QUERY_SKIP_CACHE        = 0x00020000

# validator error codes
VAL_NOT_IMPLEMENTED         = -1
VAL_RESOURCE_UNAVAILABLE    = -2
VAL_BAD_ARGUMENT            = -3
VAL_INTERNAL_ERROR          = -4
VAL_NO_PERMISSION           = -5
VAL_CONF_PARSE_ERROR        = -6
VAL_CONF_NOT_FOUND          = -7
VAL_NO_POLICY               = -8

VAL_AC_VERIFIED             = 31

# validator result codes

VAL_FLAG_CHAIN_COMPLETE     = 0x80

VAL_SUCCESS                         =  0 | VAL_FLAG_CHAIN_COMPLETE
VAL_BOGUS                           =  1 
VAL_DNS_ERROR                       =  2
VAL_NOTRUST                         =  3
VAL_NONEXISTENT_NAME                =  4 | VAL_FLAG_CHAIN_COMPLETE
VAL_NONEXISTENT_TYPE                =  5 | VAL_FLAG_CHAIN_COMPLETE
VAL_NONEXISTENT_NAME_NOCHAIN        =  6 | VAL_FLAG_CHAIN_COMPLETE
VAL_NONEXISTENT_TYPE_NOCHAIN        =  7 | VAL_FLAG_CHAIN_COMPLETE
VAL_NONEXISTENT_PINSECURE           =  8 | VAL_FLAG_CHAIN_COMPLETE
VAL_NONEXISTENT_PINSECURE_UNTRUSTED =  9 | VAL_FLAG_CHAIN_COMPLETE
VAL_BARE_RRSIG                      = 10 | VAL_FLAG_CHAIN_COMPLETE
VAL_IGNORE_VALIDATION               = 11 | VAL_FLAG_CHAIN_COMPLETE
VAL_UNTRUSTED_ZONE                  = 12 | VAL_FLAG_CHAIN_COMPLETE
VAL_OOB_ANSWER                      = 13 | VAL_FLAG_CHAIN_COMPLETE
VAL_TRUSTED_ANSWER                  = 14 | VAL_FLAG_CHAIN_COMPLETE
VAL_VALIDATED_ANSWER                = 15 | VAL_FLAG_CHAIN_COMPLETE
VAL_UNTRUSTED_ANSWER                = 16 | VAL_FLAG_CHAIN_COMPLETE

# action codes
VAL_CTX_FLAG_SET                    = 0x01
VAL_CTX_FLAG_RESET                  = 0x02


val_context_t = c_void_p
val_status_t  = c_uint8
val_astatus_t = c_uint16
sockaddr      = c_ulong  #questionable but hopefully harmless
size_t        = c_uint64 #long unsigned int
val_rc_proofs = c_uint   #questionable but hopefully harmless
val_log_t     = c_void_p

MAX_PROOFS = 4

class ValidatorException(Exception):
    """
    Raised if one of the libval API returns an error, but they 
    don't seem to.
    """
    def __init__(self, reason):
        super(ValidatorException, self).__init__()
        self.reason = reason

class val_rr_rec(Structure):
    pass

val_rr_rec._fields_ = \
    [("rr_rdata_length",      size_t),
     ("rr_data",              POINTER(c_ubyte)),
     ("rr_next",              POINTER(val_rr_rec)),
     ("rr_status",            val_astatus_t)]

class val_rrset_rec(Structure):
    pass

val_rrset_rec._fields_ = \
    [("val_rrset_rcode",      c_int32),
     ("val_rrset_name",       c_char_p),
     ("val_rrset_class",      c_int32),
     ("val_rrset_type",       c_int32),
     ("val_rrset_ttl",        c_int64),
     ("val_rrset_section",    c_int32),
     ("val_rrset_server",     POINTER(sockaddr)),
     ("val_rrset_data",       POINTER(val_rr_rec)),
     ("val_rrset_sig",        POINTER(val_rr_rec))]

class val_authentication_chain(Structure):
    pass

val_authentication_chain._fields_ = \
    [("val_ac_status",        val_astatus_t),
     ("val_ac_rrset",         POINTER(val_rrset_rec)),
     ("val_ac_trust",         POINTER(val_authentication_chain))]

class val_result_chain(Structure):
    pass

val_result_chain._fields_ = \
    [("val_rc_status",        val_status_t),
     ("val_rc_alias",         c_char_p),
     ("val_rc_rrset",         POINTER(val_rrset_rec)),
     ("val_rc_answer",        POINTER(val_authentication_chain)),
     ("val_rc_proof_count",   c_int32),
     ("val_rc_proofs",        POINTER(val_authentication_chain * MAX_PROOFS)),
     ("val_rc_next",          POINTER(val_result_chain))]


class Validator(object):
    """
    wraps libval-threads methods discussed in man libval(3).
    """
    
    def __init__(self, label=None):

        #Get a handle to the shared libraries. 
        if sys.platform == 'win32':
            #Windows
            CDLL('libsres.dll', RTLD_GLOBAL)
            libval  = CDLL('libval-threads.dll')
        elif sys.platform == 'darwin':
            #mac
            CDLL('libcrypto.dylib', RTLD_GLOBAL)
            CDLL('libsres.dylib', RTLD_GLOBAL)
            libval    = CDLL('libval-threads.dylib')
        elif sys.platform == 'linux2':
            #linux
            CDLL('libsres.so', RTLD_GLOBAL)
            libval  = CDLL('libval-threads.so')
        else:
            raise ValidatorException("Unknown platform - %s" % (sys._platform, ))
        
        #build the calls to libval-threads functions
        
        #val_create_context
        self._create_context = libval.val_create_context
        self._create_context.restype = c_int
        self._create_context.argtypes = [c_char_p, POINTER(POINTER(val_context_t))]
        
        #val_free_context
        self._free_context = libval.val_free_context
        self._free_context.restype = None
        self._free_context.argtypes = [POINTER(val_context_t)]
        
        #val_resolve_and_check
        self._resolve_and_check = libval.val_resolve_and_check
        self._resolve_and_check.restype = c_int
        self._resolve_and_check.argtypes = [POINTER(val_context_t), c_char_p, c_int, c_int, c_uint, POINTER(POINTER(val_result_chain))]

        #val_free_result_chain
        self._free_result_chain = libval.val_free_result_chain
        self._free_result_chain.restype = None
        self._free_result_chain.argtypes = [POINTER(val_result_chain)]

        #val_context_setqflags
        self._val_context_setqflags = libval.val_context_setqflags
        self._val_context_setqflags.restype = c_int
        self._val_context_setqflags.argtypes = [POINTER(val_context_t), c_uint8, c_uint32]

        #val_istrusted
        self._val_istrusted = libval.val_istrusted
        self._val_istrusted.restype = c_int
        self._val_istrusted.argtypes = [val_status_t]

        #val_isvalidated
        self._val_isvalidated = libval.val_isvalidated
        self._val_isvalidated.restype = c_int
        self._val_isvalidated.argtypes = [val_status_t]

        #val_does_not_exist
        self._val_does_not_exist = libval.val_does_not_exist
        self._val_does_not_exist.restype = c_int
        self._val_does_not_exist.argtypes = [val_status_t]
        
        #p_val_status
        self._p_val_status = libval.p_val_status
        self._p_val_status.restype = c_char_p
        self._p_val_status.argtypes = [val_status_t]
        
        #p_ac_status
        self._p_ac_status = libval.p_ac_status
        self._p_ac_status.restype = c_char_p
        self._p_ac_status.argtypes = [val_astatus_t]
                
        #p_val_error is #define'd as p_val_status
        self._p_val_error = self._p_val_status
        
        #p_val_log_add_optarg
        self._val_log_add_optarg = libval.val_log_add_optarg
        self._val_log_add_optarg.restype = val_log_t
        self._val_log_add_optarg.argtypes = [c_char_p, c_int32]
      
        contextBuf = create_string_buffer(sizeof(val_context_t))
        self.pContext = cast(contextBuf, POINTER(val_context_t))
        status = self._create_context(label, byref(self.pContext)) 
        if status != 0:
            raise ValidatorException(status)        

    def __del__(self):
        """
        free the context returned by createContext.
        """
        self._free_context(self.pContext)
    
      
    def setFlags(self, action, flags):
        """
        set/reset validator flags on context
        (so you don't have to pass them in resolveAndCheck calls)
        """
        return self._val_context_setqflags(self.pContext, action, flags)
        
    def resolveAndCheck(self, domainName, rdclass, rdtype, flags=0):
        """
        resolve a domain and check its dnssec validity.
        """
        pResultsBuf = create_string_buffer(sizeof(val_result_chain))
        pResults = cast(pResultsBuf, POINTER(val_result_chain))
        status = self._resolve_and_check(self.pContext, domainName, rdclass, rdtype, flags, byref(pResults))
        if status != 0:
            raise ValidatorException(status)
        return pResults
    
    def freeResultChain(self, pResults):
        """
        free the result chain returned by resolveAndCheck.
        """
        self._free_result_chain(pResults)
        
    def isTrusted(self, status):
        """
        check val_status_t type for trusted.
        """
        return self._val_istrusted(status)
    
    def isValidated(self, status):
        """
        check val_status_t type for validated.
        """
        return self._val_isvalidated(status)
    
    def doesNotExist(self, status):
        """
        check val_status_t type for non-existence.
        """
        return self._val_does_not_exist(status)
    
    def fmtValStatus(self, valStatus):
        """
        format a val_status_t object.
        """
        return self._p_val_status(valStatus)
    
    def fmtAcStatus(self, valAcStatus):
        """
        format a val_astatus_t object.
        """
        return self._p_ac_status(valAcStatus)
    
    def logAddOptarg(self, args, useStderr):
        """
        set optional args on the validator logging.
        """
        return self._val_log_add_optarg(args, useStderr)