def ensureCertificateExists(self, name): certname = "%s-cert.pem" % name keyname = "%s-key.pem" % name reqname = "%s-req.pem" % name if self.hasfile(certname) and self.hasfile(keyname): return True # No cert/key in repository log_info("Creating certificate for %s" % name) sParams = self.getCAParameters().copy() sParams["CN"] = name sParams["emailAddress"] = "root@%s" % \ config_get_required("network", "domain") # Generate the new key / request (csr, key) = createKey(0, sParams) # Get it signed cert = self.signReq(csr) # Add it to the repository for safe-keeping try: a = self.addfile(certname, cert) b = self.addfile(keyname, key) c = self.addfile(reqname, csr) self.checkin("Added %s certificate and key" % name, [a, b, c]) return True except ccs_ca_error: (type, value, tb) = sys.exc_info() log_error("CA: Failed to create key for %s: %s" % \ (name, value), (type, value, tb)) return False
def initialiseService(): """Called by the system the very first time the service is loaded. This should setup an entry in the service table and load any default service properties into the service_prop table. """ session = getSessionE(ADMIN_SESSION_ID) session.begin("initialising RADIUS service") try: session.execute("INSERT INTO service (service_id, service_name, " \ "enabled) VALUES (DEFAULT, %s, DEFAULT)", \ (radius_service.serviceName)) service_id = session.getCountOf("SELECT currval('" \ "service_service_id_seq') AS server_id", ()) default_ip = getIP(config_get_required("network", "server_name")) session.execute("INSERT INTO service_prop (service_prop_id, " \ "service_id, prop_name, prop_type, default_value, " \ "required) VALUES (DEFAULT, %s, %s, 'string', %s, 'f')", \ (service_id, AUTHIP_PROPERTY, default_ip)) session.execute("INSERT INTO service_prop (service_prop_id, " \ "service_id, prop_name, prop_type, default_value, " \ "required) VALUES (DEFAULT, %s, %s, 'string', %s, 'f')", \ (service_id, ACCTIP_PROPERTY, default_ip)) session.execute("INSERT INTO service_prop (service_prop_id, " \ "service_id, prop_name, prop_type, default_value, " \ "required) VALUES (DEFAULT, %s, %s, 'integer', %s, 'f')", \ (service_id, AUTHPORT_PROPERTY, 1812)) session.execute("INSERT INTO service_prop (service_prop_id, " \ "service_id, prop_name, prop_type, default_value, " \ "required) VALUES (DEFAULT, %s, %s, 'integer', %s, 'f')", \ (service_id, ACCTPORT_PROPERTY, 1813)) # Commit the changese session.commit() log_info("Created radius service entries and tables in database") except: session.rollback() log_error("Unable to initialise radius database entries!", \ sys.exc_info()) raise ccs_radius_error("Failed to setup database tables!") return service_id
def initConfFile(self): """Initialises the CA configuration file""" signdays = config_get("ca", "signdays", DEFAULT_SIGN_DAYS) site_name = config_get_required("network", "site_name") domain = config_get_required("network", "domain") fd = open("%s/ca.cnf" % self.rDir, "w") fd.write("""# # OpenSSL configuration file for the CRCnet Configuration System CA # This definition stops the following lines choking if HOME isn't # defined. HOME = . RANDFILE = $ENV::HOME/.rnd #################################################################### [ ca ] default_ca = CA_default # The default ca section #################################################################### [ CA_default ] dir = $ENV::CCS_CA_DIR # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/certs # default place for new certs. certificate = $dir/cacert.pem # The CA certificate private_key = $dir/cakey.pem # The private key serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number crl = $dir/crl.pem # The current CRL RANDFILE = $dir/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = %s # how long to certify for default_crl_days = 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering policy = policy_match # For the CA policy [ policy_match ] countryName = match stateOrProvinceName = optional localityName = optional organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_anything ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional #################################################################### [ req ] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # Extensions to add to self signed certs string_mask = nombstr [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = NZ countryName_min = 2 countryName_max = 2 localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) 0.organizationName_default = %s organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = CRCnet Configuration System commonName = Common Name (eg, YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [ req_attributes ] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 unstructuredName = An optional company name # These extensions are added when 'ca' signs a request. [ usr_cert ] basicConstraints = CA:FALSE # nsCertType = server # nsCertType = client # This will be displayed in Netscape's comment listbox. nsComment = "Signed by the CRCnet Configuration System" # PKIX recommendations harmless if included in all certificates. subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer nsRevocationUrl = https://%s/certs/crl.pem # Extensions to add to a certificate request [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment # Extensions for a typical CA [ v3_ca ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always basicConstraints = CA:true # CRL extensions. [ crl_ext ] authorityKeyIdentifier = keyid:always,issuer:always """ % (signdays, site_name, domain)) fd.close() client.svn_client_add("%s/ca.cnf" % self.rDir, False, \ self.ctx, self.pool) log_info("CA: Initialised configuration file") return
def ifAccountThread(): """Runs as a thread to account from traffic on an interface""" global _accountingInfo, _runIfAccount, nas_id, nas_ip global radius_update_interval, radius_acct_server, radius_auth_server try: # Is interface accounting enabled enabled = config_getboolean("accounting", "enabled", True) if not enabled: log_info("Interface accounting disabled.") return _runIfAccount = True # What interval shall we check hosts at check_interval = config_get("accounting", "check_interval", DEFAULT_CHECK_INTERVAL) radius_update_interval = config_getint("accounting", "update_interval", DEFAULT_UPDATE_INTERVAL) # Initialise the interface list default_user_file = "%s/accounting_users" % os.path.dirname(DEFAULT_CONFFILE) user_file = config_get("accounting", "user_file", default_user_file) if not os.path.exists(user_file): log_error("Interface accounting disabled. No user file: %s" % user_file) _runIfAccount = False return # Initialise the RADIUS connection try: dummy0 = getInterfaces(returnOne="dummy0")[0] dummy0ip = dummy0["address"].split("/")[0] except: log_error("Could not determine host loopback address!", sys.exc_info()) dummy0ip = "127.0.0.1" acct_server = config_get("accounting", "acct_server", "radius") acct_secret = config_get_required("accounting", "acct_secret") auth_server = config_get("accounting", "auth_server", "radius") auth_secret = config_get_required("accounting", "auth_secret") nas_id = config_get("accounting", "nas_id", getFQDN()) nas_ip = config_get("accounting", "nas_ip", dummy0ip) radius_acct_server = Client(server=acct_server, secret=acct_secret, dict=Dictionary(RADIUS_DICTIONARY)) radius_auth_server = Client(server=auth_server, secret=auth_secret, dict=Dictionary(RADIUS_DICTIONARY)) # FreeRADIUS at least auths based on IP address, make sure our # packets come from the right place radius_acct_server.bind((nas_ip, 0)) radius_auth_server.bind((nas_ip, 0)) # Read and parse the user file parseUserFile(user_file) # Initialise interface state initialiseInterfaceState() # Loop forever reading byte counters as appropriate while _runIfAccount: # wait a bit before checking time.sleep(check_interval) # Send any queued packets processRADIUSQueue() # Try and re-authenticate any dead interfaces for ifname, iface in _accountingInfo.items(): if iface["authenticated"]: continue age = time.time() - iface["last_auth_check"] if age > radius_update_interval: doRADIUSAuthentication(ifname) # Update traffic details updateTrafficCounters() # Generate interim-updates processInterimUpdates() except: (etype, value, tb) = sys.exc_info() log_error("Exception in interface accounting thread! - %s" % value, (etype, value, tb)) log_info("Exiting interface accounting thread")