diff --git a/app/assets/javascripts/pamela.js.coffee b/app/assets/javascripts/pamela.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/pamela.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/pamela.css.scss b/app/assets/stylesheets/pamela.css.scss new file mode 100644 index 0000000..1f2fc52 --- /dev/null +++ b/app/assets/stylesheets/pamela.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the pamela controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/pamela_controller.rb b/app/controllers/pamela_controller.rb new file mode 100644 index 0000000..f47115e --- /dev/null +++ b/app/controllers/pamela_controller.rb @@ -0,0 +1,189 @@ +class PamelaController < ApplicationController + +#require "active_record" +require "optparse" +#require "rubygems" + +def index + @macs = Mac.all +end + + # GET /macs/1 + # GET /macs/1.json + def show + @mac = Mac.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render :json => @macs } + end + end + + # GET /macs/new + # GET /macs/new.json + def new + @mac = Mac.new + @users = User.all.sort_by(&:name) + + respond_to do |format| + format.html # new.html.erb + format.json { render :json => @mac } + end + end + + # GET /macs/1/edit + def edit + @mac = Mac.find(params[:id]) + @users = User.all.sort_by(&:name) + end + + # POST /macs + # POST /user + def create + @mac = Mac.new(params[:mac]) + + respond_to do |format| + if @mac.save + format.html { redirect_to "/pamela", :notice => 'Mac was successfully created.' } + format.json { render :json => @mac, :status => :created, :location => @mac } + else + format.html { render :action => "new" } + format.json { render :json => @mac.errors, :status => :unprocessable_entity } + end + end + end + + # PUT /macs/1 + # PUT /macs/1.json + def update + #Log who updated this + @mac = Mac.find(params[:id]) + + respond_to do |format| + if @mac.update_attributes(params[:mac]) + format.html { redirect_to "/pamela", :notice => 'User certification was successfully updated.' } + format.json { head :no_content } + else + format.html { render :action => "edit" } + format.json { render :json => @mac.errors, :status => :unprocessable_entity } + end + end + end + + + +def scan +Rails.logger.info "starting scan..." + # Command line arguments + options = {}; + OptionParser.new { |opts| + opts.banner = "Usage: pamela-scanner.rb --interface=en0" + + options[:verbose] = true + opts.on("v", "--verbose", "Run verbosely") { |verbose| + options[:verbose] = verbose + } + + options[:interface] = "eth0" + opts.on("i", "--interface=interface", "Network Interface") { |interface| + options[:interface] = interface + } + + options[:max_age] = 20 + opts.on("a", "--max-age=minutes", "Minutes to keep expired macs active") { |max_age| + options[:max_age] = max_age.to_i + } + + options[:db_host] = "configure_me" + opts.on("r", "--db-host=host", "Database Host") { |host| + options[:db_host] = host + } + + options[:db_name] = "configure_me" + opts.on("n", "--db-name=name", "Database Name") { |name| + options[:db_name] = name + } + + options[:db_user] = "configure_me" + opts.on("u", "--db-user=user", "Database User") { |user| + options[:db_user] = user + } + + options[:db_password] = "configure_me" + opts.on("p", "--db-password=password", "Database Password") { |password| + options[:db_password] = password + } + + }.parse! + + # Open the database + #ActiveRecord::Base::establish_connection( + # :adapter => "mysql2", + # :host => options[:db_host], + # :database => options[:db_name], + # :username => options[:db_user], + # :password => options[:db_password]) + + #class Mac < ActiveRecord::Base + #end + + #class MacLog < ActiveRecord::Base + #end + + # Scan the network for mac addresses + macs = {}; + command = sprintf("arp-scan -R --interface=%s --localnet", options[:interface]) + if options[:verbose] + Rails.logger.info "Running [#{command}]" + end + IO.popen(command) { |stdin| + Rails.logger.info "Reading stdin: "+stdin.inspect + stdin.each { |line| + next if line !~ /^([\d\.]+)\s+([[:xdigit:]:]+)\s/; + macs[$2] = $1; + } + } + + # Scan the existing macs and update each record as necessary + Mac.find(:all).each { |entry| + Rails.logger.info "Existing MAC: "+entry.inspect + mac = entry.mac + ip = entry.ip + if macs.has_key?(mac) + if ! entry.active || ! entry.since + Rails.logger.info "Activating #{mac} at #{ip}" if options[:verbose] + entry.since = Time.now + MacLog.new(:mac => mac, :ip => ip, :action => "activate").save + end + entry.active = 1 + entry.ip = ip + entry.refreshed = Time.now + entry.save + macs.delete(mac) + next + end + + # Entry is no longer current + if entry.active + ageMinutes = ((Time.now - entry.refreshed)/60).to_i + next if ageMinutes < options[:max_age] + Rails.logger.info "Deactivating #{mac}, #{ageMinutes} minutes old" if options[:verbose] + entry.active = 0 + entry.save + MacLog.new(:mac => mac, :ip => ip, :action => "deactivate").save + end + } + + # Add entries for any macs not already in the db + macs.each { |mac, ip| + Rails.logger.info "Activating new entry #{mac} at #{ip}" if options[:verbose] + Mac.new(:mac => mac, :ip => ip, :active => 1, :since => Time.now, :refreshed => Time.now).save + MacLog.new(:mac => mac, :ip => ip, :action => "activate").save + } + +@log = MacLog.all + +end #def scan + + +end diff --git a/app/helpers/pamela_helper.rb b/app/helpers/pamela_helper.rb new file mode 100644 index 0000000..c42e8a9 --- /dev/null +++ b/app/helpers/pamela_helper.rb @@ -0,0 +1,2 @@ +module PamelaHelper +end diff --git a/app/models/mac.rb b/app/models/mac.rb new file mode 100644 index 0000000..fe3c903 --- /dev/null +++ b/app/models/mac.rb @@ -0,0 +1,4 @@ +class Mac < ActiveRecord::Base + belongs_to :user + attr_accessible :active, :ip, :mac, :refreshed, :since +end diff --git a/app/models/mac_log.rb b/app/models/mac_log.rb new file mode 100644 index 0000000..142c825 --- /dev/null +++ b/app/models/mac_log.rb @@ -0,0 +1,3 @@ +class MacLog < ActiveRecord::Base + attr_accessible :action, :ip, :mac +end diff --git a/app/views/pamela/_form.html.erb b/app/views/pamela/_form.html.erb new file mode 100644 index 0000000..9759232 --- /dev/null +++ b/app/views/pamela/_form.html.erb @@ -0,0 +1,25 @@ +<%= form_for(@mac) do |f| %> + <% if @mac.errors.any? %> +