| Lines 45-50
          import time
      
      
        Link Here | 
        
          | 45 | import errno | 45 | import errno | 
        
          | 46 | import signal | 46 | import signal | 
        
          | 47 | import grp | 47 | import grp | 
            
              |  |  | 48 | import urllib | 
        
          | 48 |  | 49 |  | 
        
          | 49 | name = 'bind' | 50 | name = 'bind' | 
        
          | 50 | description = 'Update BIND zones' | 51 | description = 'Update BIND zones' | 
  
    | Lines 98-106
          def handler(dn, new, old):
      
      
        Link Here | 
        
          | 98 | 			_remove_zone(old['zoneName'][0]) | 99 | 			_remove_zone(old['zoneName'][0]) | 
        
          | 99 | 		if new.get('zoneName'): | 100 | 		if new.get('zoneName'): | 
        
          | 100 | 			# Change | 101 | 			# Change | 
          
            
              | 101 | 			# Create an empty file to trigger the postrun() | 102 | 			# Create a file to trigger the postrun() | 
            
              | 102 | 			zonefile = os.path.join(PROXY_CACHE_DIR, "%s.zone" % (new['zoneName'][0],)) | 103 | 			zone = new['zoneName'][0] | 
            
              |  |  | 104 | 			zonefile = sanitized_path_join(PROXY_CACHE_DIR, "%s.zone" % (zone, )) | 
        
          | 103 | 			proxy_cache = open(zonefile, 'w') | 105 | 			proxy_cache = open(zonefile, 'w') | 
            
              |  |  | 106 | 			proxy_cache.write(zone) | 
        
          | 104 | 			proxy_cache.close() | 107 | 			proxy_cache.close() | 
        
          | 105 | 			os.chmod(zonefile, 0o640) | 108 | 			os.chmod(zonefile, 0o640) | 
        
          | 106 | 			chgrp_bind(zonefile) | 109 | 			chgrp_bind(zonefile) | 
  
    | Lines 125-131
          def _new_zone(ucr, zonename, dn):
      
      
        Link Here | 
        
          | 125 | 		os.mkdir(NAMED_CONF_DIR) | 128 | 		os.mkdir(NAMED_CONF_DIR) | 
        
          | 126 | 		os.chmod(NAMED_CONF_DIR, 0o755) | 129 | 		os.chmod(NAMED_CONF_DIR, 0o755) | 
        
          | 127 |  | 130 |  | 
          
            
              | 128 | 	zonefile = os.path.join(NAMED_CONF_DIR, zonename) | 131 | 	zonefile = sanitized_path_join(NAMED_CONF_DIR, zonename) | 
        
          | 129 |  | 132 |  | 
        
          | 130 | 	# Create empty file and restrict permission | 133 | 	# Create empty file and restrict permission | 
        
          | 131 | 	named_zone = open(zonefile, 'w') | 134 | 	named_zone = open(zonefile, 'w') | 
  
    | Lines 149-159
          def _new_zone(ucr, zonename, dn):
      
      
        Link Here | 
        
          | 149 | 	named_zone.close() | 152 | 	named_zone.close() | 
        
          | 150 |  | 153 |  | 
        
          | 151 | 	# Create proxy configuration file | 154 | 	# Create proxy configuration file | 
          
            
              | 152 | 	proxy_file = os.path.join(NAMED_CONF_DIR, zonename + '.proxy') | 155 | 	proxy_file = sanitized_path_join(NAMED_CONF_DIR, zonename + '.proxy') | 
        
          | 153 | 	proxy_zone = open(proxy_file, 'w') | 156 | 	proxy_zone = open(proxy_file, 'w') | 
        
          | 154 | 	proxy_zone.write('zone "%s" {\n' % (zonename,)) | 157 | 	proxy_zone.write('zone "%s" {\n' % (zonename,)) | 
        
          | 155 | 	proxy_zone.write('\ttype slave;\n') | 158 | 	proxy_zone.write('\ttype slave;\n') | 
          
            
              | 156 | 	proxy_zone.write('\tfile "%s.zone";\n' % (zonename,)) | 159 | 	proxy_zone.write('\tfile "%s.zone";\n' % (sanitize_filename(zonename),)) | 
        
          | 157 | 	proxy_zone.write('\tmasters port 7777 { 127.0.0.1; };\n') | 160 | 	proxy_zone.write('\tmasters port 7777 { 127.0.0.1; };\n') | 
        
          | 158 | 	proxy_zone.write('};\n') | 161 | 	proxy_zone.write('};\n') | 
        
          | 159 | 	proxy_zone.close() | 162 | 	proxy_zone.close() | 
  
    | Lines 167-174
          def _new_zone(ucr, zonename, dn):
      
      
        Link Here | 
        
          | 167 | def _remove_zone(zonename): | 170 | def _remove_zone(zonename): | 
        
          | 168 | 	"""Handle removal of zone.""" | 171 | 	"""Handle removal of zone.""" | 
        
          | 169 | 	ud.debug(ud.LISTENER, ud.INFO, 'DNS: Removing zone %s' % (zonename,)) | 172 | 	ud.debug(ud.LISTENER, ud.INFO, 'DNS: Removing zone %s' % (zonename,)) | 
          
            
              | 170 | 	zonefile = os.path.join(NAMED_CONF_DIR, zonename) | 173 | 	zonefile = sanitized_path_join(NAMED_CONF_DIR, zonename) | 
            
              | 171 | 	cached_zonefile = os.path.join(NAMED_CACHE_DIR, zonename + '.zone') | 174 | 	cached_zonefile = sanitized_path_join(NAMED_CACHE_DIR, zonename + '.zone') | 
        
          | 172 | 	# Remove zone file | 175 | 	# Remove zone file | 
        
          | 173 | 	if os.path.exists(zonefile): | 176 | 	if os.path.exists(zonefile): | 
        
          | 174 | 		os.unlink(zonefile) | 177 | 		os.unlink(zonefile) | 
  
    | Lines 318-330
          def postrun():
      
      
        Link Here | 
        
          | 318 | 				__zone_created_or_removed = False | 321 | 				__zone_created_or_removed = False | 
        
          | 319 | 		elif dns_backend == 'ldap': | 322 | 		elif dns_backend == 'ldap': | 
        
          | 320 | 			for filename in os.listdir(PROXY_CACHE_DIR): | 323 | 			for filename in os.listdir(PROXY_CACHE_DIR): | 
          
            
              | 321 | 				os.remove(os.path.join(PROXY_CACHE_DIR, filename)) | 324 | 				filepath = os.path.join(PROXY_CACHE_DIR, filename) | 
            
              |  |  | 325 | 				zone = open(filepath, 'rb').read() | 
            
              | 326 | 				os.remove(filepath) | 
        
          | 322 | 				if not os.path.exists(os.path.join(NAMED_CACHE_DIR, filename)): | 327 | 				if not os.path.exists(os.path.join(NAMED_CACHE_DIR, filename)): | 
        
          | 323 | 					ud.debug(ud.LISTENER, ud.PROCESS, 'DNS: %s does not exist. Triggering a bind9 restart.' % (os.path.join(NAMED_CACHE_DIR, filename))) | 328 | 					ud.debug(ud.LISTENER, ud.PROCESS, 'DNS: %s does not exist. Triggering a bind9 restart.' % (os.path.join(NAMED_CACHE_DIR, filename))) | 
        
          | 324 | 					restart = True | 329 | 					restart = True | 
        
          | 325 | 				else: | 330 | 				else: | 
          
            
              | 326 | 					zone = filename.replace(".zone", "") | 331 | 					_, ext = os.path.splitext(filename) | 
            
              | 327 | 					zones.append(zone) | 332 | 					if ext == '.zone': | 
            
              |  |  | 333 | 						zones.append(zone) | 
            
              | 334 | 					else: | 
            
              | 335 | 						ud.debug(ud.LISTENER, ud.WARN, 'DNS: strange file in PROXY_CACHE_DIR: %r' % (filename, )) | 
        
          | 328 | 			if zones: | 336 | 			if zones: | 
        
          | 329 | 				ud.debug(ud.LISTENER, ud.INFO, 'DNS: Zones: %s' % (zones,)) | 337 | 				ud.debug(ud.LISTENER, ud.INFO, 'DNS: Zones: %s' % (zones,)) | 
        
          | 330 | 		elif dns_backend == 'none': | 338 | 		elif dns_backend == 'none': | 
  
    | Lines 341-343
          def postrun():
      
      
        Link Here | 
        
          | 341 | 		_kill_children(pids) | 349 | 		_kill_children(pids) | 
        
          | 342 | 	finally: | 350 | 	finally: | 
        
          | 343 | 		listener.unsetuid() | 351 | 		listener.unsetuid() | 
            
              |  |  | 352 |  | 
            
              | 353 | def sanitize_filename(bytestring): | 
            
              | 354 | 	escaped = urllib.quote(bytestring, safe='') | 
            
              | 355 | 	if escaped.startswith('.'): # always encode leading dot because '.' and '..' are special names | 
            
              | 356 | 		escaped = '%20' + escaped[1:] | 
            
              | 357 | 	return escaped | 
            
              | 358 |  | 
            
              | 359 | def sanitized_path_join(directory, unsafe_filename): | 
            
              | 360 | 	filename = sanitize_filename(unsafe_filename) | 
            
              | 361 | 	assert '/' not in filename | 
            
              | 362 | 	assert '\0' not in filename | 
            
              | 363 | 	assert filename not in ('.', '..', ) | 
            
              | 364 | 	return os.path.join(directory, filename) |