Merge branch 'master' of defaria.com:/opt/git/clearscm
authorAndrew DeFaria <andrew@earth>
Fri, 4 Nov 2016 01:04:50 +0000 (18:04 -0700)
committerAndrew DeFaria <andrew@earth>
Fri, 4 Nov 2016 01:04:50 +0000 (18:04 -0700)
1  2 
audience/getPicture.conf
audience/getPicture.pl
bin/bice.py
bin/rexec.new
bin/test.py
maps/test.msg
maps/test.pl
rc/sshconfig
test/test.py

index 0000000,0000000..a04c3b3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,21 @@@
++################################################################################
++#
++# File:         getPicture.conf
++# Description:  Configuration file for getPicture.pl
++# Author:       Andrew DeFaria <Andrew@ClearSCM.com>
++# Version:      1.0
++# Created:      Fri Oct  3 18:16:26 PDT 2014
++# Modified:     $Date: 2014/10/03 18:17:20 $
++# Language:     Conf
++#
++# This file contains configurable parameters that are unique to your site that
++# identify the LDAP parms needed to retrieve users pictures from Active 
++# Directory. It is assumed that thumbnailPhoto is the attribute name and that
++# the user can be found by their unique uid.
++#
++################################################################################
++AD_HOST:     <host name of your LDAP server>
++AD_PORT:     <LDAP Port - normally 389>
++AD_BINDDN:   <DN of user you have to use to bind to the LDAP server>
++AD_BINDPW:   <The bind user's password>
++AD_BASEDN:   <Base DN of where to start the search>
index 0000000,0000000..e74ee10
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,202 @@@
++#!/usr/bin/env perl
++use strict;
++use warnings;
++
++=pod
++
++=head1 NAME getPicture.pl
++
++Retrieve thumbnailPhoto for the userid from Active Directory
++
++=head1 VERSION
++
++=over
++
++=item Author
++
++Andrew DeFaria <Andrew@ClearSCM.com>
++
++=item Revision
++
++$Revision: #8 $
++
++=item Created
++
++Fri Oct  3 18:16:26 PDT 2014
++
++=item Modified
++
++$Date: 2014/10/03 18:17:20 $
++
++=back
++
++=head1 DESCRIPTION
++
++This script will take a userid and search the Active Directory for the user and
++return an image file if the user has an image associated with his 
++thumbnailPhoto attribute.
++
++This can be configured into Perforce Swarn as documented:
++
++http://www.perforce.com/perforce/doc.current/manuals/swarm/admin.avatars.html
++
++One would use something like
++
++  // this block should be a peer of 'p4'
++  'avatars' => array(
++    'http_url'  => 'http://<server>/cgi-bin/getPicture.pl?userid={user}'
++    'https_url' => 'http://<server>/cgi-bin/getPicture.pl?userid={user}',
++  ),
++
++=cut
++
++use FindBin;
++use Getopt::Long;
++use Net::LDAP;
++use CGI qw (:standard);
++
++# Interpolate variable in str (if any) from %opts
++sub interpolate ($%) {
++  my ($str, %opts) = @_;
++
++  # Since we wish to leave undefined $var references in tact the following while
++  # loop would loop indefinitely if we don't change the variable. So we work
++  # with a copy of $str changing it always, but only changing the original $str
++  # for proper interpolations.
++  my $copyStr = $str;
++
++  while ($copyStr =~ /\$(\w+)/) {
++    my $var = $1;
++
++    if (exists $opts{$var}) {
++      $str     =~ s/\$$var/$opts{$var}/;
++      $copyStr =~ s/\$$var/$opts{$var}/;
++    } elsif (exists $ENV{$var}) {
++      $str     =~ s/\$$var/$ENV{$var}/;
++      $copyStr =~ s/\$$var/$ENV{$var}/;
++    } else {
++     $copyStr =~ s/\$$var//;
++  } # if
++ } # while
++
++ return $str;
++} # interpolate
++
++sub _processFile ($%) {
++  my ($configFile, %opts) = @_;
++  
++  while (<$configFile>) {
++    chomp;
++
++    next if /^\s*[\#|\!]/;    # Skip comments
++
++    if (/\s*(.*?)\s*[:=]\s*(.*)\s*/) {
++      my $key   = $1;
++      my $value = $2;
++
++      # Strip trailing spaces
++      $value =~ s/\s+$//;
++
++      # Interpolate
++      $value = interpolate $value, %opts;
++
++      if ($opts{$key}) {
++        # If the key exists already then we have a case of multiple values for 
++        # the same key. Since we support this we need to replace the scalar
++        # value with an array of values...
++        if (ref $opts{$key} eq "ARRAY") {
++          # It's already an array, just add to it!
++          push @{$opts{$key}}, $value;
++        } else {
++          # It's not an array so make it one
++          my @a;
++
++          push @a, $opts{$key};
++          push @a, $value;
++          $opts{$key} = \@a;
++        } # if
++      } else {
++        # It's a simple value
++        $opts{$key} = $value;
++      }  # if
++    } # if
++  } # while
++  
++  return %opts;
++} # _processFile
++
++sub GetConfig ($) {
++  my ($filename) = @_;
++
++  my %opts;
++
++  open my $configFile, '<', $filename
++    or die "Unable to open config file $filename";
++
++  %opts = _processFile $configFile;
++
++  close $configFile;
++
++  return %opts;
++} # GetConfig
++
++sub checkLDAPError ($$) {
++  my ($msg, $result) = @_;
++  
++  my $code = $result->code;
++  
++  die "$msg (Error $code)\n" . $result->error if $code;
++} # checkLDAPError
++
++my ($confFile) = ($FindBin::Script =~ /(.*)\.pl$/);
++    $confFile = "$confFile.conf";
++
++my %opts = GetConfig ($confFile);
++
++## Main
++$| = 1;
++
++GetOptions (
++  \%opts,
++  'AD_HOST=s',
++  'AD_PORT=s',
++  'AD_BINDDN=s',
++  'AD_BINDPW=s',
++  'AD_BASEDN=s',
++  'userid=s', 
++) || die 'Invalid parameters';
++
++$opts{userid} = param 'userid' unless $opts{userid};
++
++die "Usage getPicture.pl [userid=]<userid>\n" unless $opts{userid};
++
++my $ldap = Net::LDAP->new (
++  $opts{AD_HOST}, (
++    host   => $opts{AD_HOST},
++    port   => $opts{AD_PORT},
++    basedn => $opts{AD_BASEDN},
++    binddn => $opts{AD_BINDDN},
++    bindpw => $opts{AD_BINDPW},
++  ),
++) or die $@;
++
++my $result = $ldap->bind (
++  dn       => $opts{AD_BINDDN},
++  password => $opts{AD_BINDPW},
++) or die "Unable to bind\n$@";
++
++checkLDAPError ('Unable to bind', $result);
++
++$result = $ldap->search (
++  base   => $opts{AD_BASEDN},
++  filter => "uid=$opts{userid}",
++);
++
++checkLDAPError ('Unable to search', $result);
++
++my @entries = ($result->entries);
++
++if ($entries[0]) {
++  print header 'image/jpeg';
++  print $entries[0]->get_value ('thumbnailPhoto');  
++} # if
diff --cc bin/bice.py
index 0000000,0000000..c5bb2f3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,153 @@@
++#!/usr/bin/python
++
++import sys
++import getopt
++import fcntl
++import re
++
++from array import *
++
++security_logfile = '/var/log/auth.log'
++verbose = False
++debug   = False
++update  = False
++email   = False
++
++def Error (msg = '', errno = 0):
++  sys.stderr.write ('Error: ' + msg)
++
++  if (errno <> 0):  
++    sys.exit (errno)
++
++def Verbose (msg, linefeed = True):
++  global verbose
++  
++  if (linefeed):
++    msg += '\n'
++    
++  if (verbose):
++    print msg
++
++def Usage (msg = ''):
++  if msg != '':
++    print msg
++    
++  print """
++Usage: bice.py [-u|sage] [-v|erbose] [-d|ebug] [-nou|pdate] [-nom|ail]
++               [-f|ilename <filename> ]
++
++Where:
++  -u|sage     Print this usage
++  -v|erbose:  Verbose mode (Default: -verbose)
++  -nou|pdate: Don't update security logfile file (Default: -update)
++  -nom|ail:   Don't send emails (Default: -mail)
++  -f|ilename: Open alternate messages file (Default: /var/log/auth.log)
++  """
++  
++  sys.exit (1)
++
++def processLogfile (logfile):
++  violations = {}
++    
++  try:
++    readlog = open (logfile)
++
++    fcntl.flock (readlog, fcntl.LOCK_EX)
++  except IOError:
++    Error ("Unable to get exclusive access to " + logfile + " - $!", 1)
++    
++  invalid_user           = re.compile ("^(\S+\s+\S+\s+\S+)\s+.*Invalid user (\w+) from (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})")
++  authentication_failure = re.compile ("^(\S+\s+\S+\s+\S+)\s+.*authentication failure.*ruser=(\S+).*rhost=(\S+)")
++  failed_password        = re.compile ("^(\S+\s+\S+\s+\S+)\s+.*Failed password for (\w+) from (\d{1,3}\.\d{1,3}\.d{1,3}\.d{1,3})")
++  
++  for newline in readlog:
++    violation = {}
++    newline = newline.strip ()
++    
++    timestamp = ''
++    user      = ''
++    ip        = ''
++    
++    for (timestamp, user, ip) in invalid_user.findall (newline):
++      continue
++      
++    for (timestamp, user, ip) in authentication_failure.findall (newline):
++      continue
++      
++    for (timestamp, user, ip) in failed_password.findall (newline):
++      continue
++     
++    if (ip == ''):
++      continue
++      
++    if (ip in violations):
++      violation = violations[ip]
++
++    if (user in violation):
++      violation[user].append (timestamp)
++    else:
++      violation[user] = [];
++      violation[user].append (timestamp)
++    
++    violations[ip] = violation
++    
++  return violations
++
++def ReportBreakins (logfile):
++  violations = processLogfile (logfile)
++  
++  nbrViolations = len (violations)
++  
++  if (nbrViolations == 0):
++    Verbose ('No violations found')
++  elif (nbrViolations == 1):
++    Verbose ('1 site attempting to violate our perimeter')
++  else:
++    Verbose ('{} violations'.format(nbrViolations))
++
++  for ip in violations:
++    print 'IP: ' + ip + ' violations:'
++    for key in sorted (violations[ip].iterkeys ()):
++      print "\t{}: {}".format (key, violations[ip][key])
++                    
++def dumpargs ():
++  global verbose, debug, update, email, security_logfile
++
++  print 'Args:'
++  print 'verbose', verbose
++  print 'debug',   debug
++  print 'update',  update
++  print 'email',   email
++  print 'file',    security_logfile
++
++def main (argv):
++  global verbose, debug, update, email, security_logfile
++  
++  try:
++    opts, args = getopt.getopt (argv, "vd", ['verbose', 'debug', 'usage', 'update', 'mail', 'file='])
++  except getopt.GetoptError:
++    Usage ();
++    sys.exit (1);
++
++  for opt, arg in opts:
++    if opt in ['-v', '--verbose']:
++      verbose = 1
++    elif opt in ['-d', '--debug']:
++      debug = 1
++    elif opt in ['-u', '--usage']:
++      Usage 
++    elif opt in ['--update']:
++      update = 1
++    elif opt in ['-m', '--mail']:
++      email = 1
++    elif opt in ['-f', '--file']:
++      security_logfile = arg
++  
++  if security_logfile == '':
++    Usage ('Must specify filename')
++    
++  ReportBreakins (security_logfile)
++#  dumpargs ()
++  
++if __name__ == '__main__':
++  main (sys.argv [1:])
diff --cc bin/rexec.new
index 0000000,0000000..016119e
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,336 @@@
++#!/usr/bin/perl
++use strict;
++use warnings;
++
++=pod
++
++=head1 NAME $RCSfile: rexec,v $
++
++Run arbitrary command on a set of machines
++
++=head1 VERSION
++
++=over
++
++=item Author
++
++Andrew DeFaria <Andrew@ClearSCM.com>
++
++=item Revision
++
++$Revision: 1.0 $
++
++=item Created:
++
++Tue Jan  8 15:57:27 MST 2008
++
++=item Modified:
++
++$Date: 2008/02/29 15:09:15 $
++
++=back
++
++=head1 SYNOPSIS
++
++ Usage: rexec [-u|sage] [-v|erbose] [-d|ebug] [-t|ype <machine type>]
++              <command>
++
++ Where:
++   -u|sage     Print this usage
++   -v|erbose:  Verbose mode
++   -d|ebug:    Print debug messages
++   -t|ype:     Machine type (Linux, Windows)
++   <command>:  Command to execute
++
++=head1 DESCRIPTION
++
++This script will perform and arbitrary command on a set of machines.
++
++=cut
++
++use FindBin;
++use Getopt::Long;
++use Pod::Usage;
++use Term::ANSIColor qw(:constants);
++use POSIX ":sys_wait_h";
++
++use lib "$FindBin::Bin/../lib", "$FindBin::Bin/../clearadm/lib";
++
++use Display;
++use Clearadm;
++use Logger;
++use Rexec;
++use Utils;
++
++my %total;
++my ($currentHost, $skip, $log);
++
++my %opts = (
++  usage    => sub { pod2usage },
++  help     => sub { pod2usage (-verbose => 2)},
++  verbose  => sub { set_verbose },
++  debug    => sub { set_debug },
++  parallel => 0,
++);
++
++my (%workerStatuses, %workerNames);
++
++sub Interrupted {
++  use Term::ReadKey;
++
++  display BLUE . "\nInterrupted execution on $currentHost" . RESET;
++
++  Stats \%total;
++
++  display_nolf "Executing on " . YELLOW . $currentHost . RESET . " - "
++    . GREEN     . BOLD . "S" . RESET . GREEN    . "kip"         . RESET . ", "
++    . CYAN      . BOLD . "C" . RESET . CYAN     . "ontinue"     . RESET . " or "
++    . MAGENTA   . BOLD . "A" . RESET . MAGENTA  . "bort run"    . RESET . " ("
++    . GREEN     . BOLD . "s" . RESET . "/"
++    . CYAN      . BOLD . "C" . RESET . "/"
++    . MAGENTA   . BOLD . "a" . RESET . ")?";
++
++  ReadMode ("cbreak");
++  my $answer = ReadKey (0);
++  ReadMode ("normal");
++
++  if ($answer eq "\n") {
++    display "c";
++  } else {
++    display $answer;
++  } # if
++
++  $answer = lc $answer;
++
++  if ($answer eq "s") {
++    *STDOUT->flush;
++    display "Skipping $currentHost";
++    $skip = 1;
++    $total{Skips}++;
++  } elsif ($answer eq "a") {
++    display RED . "Aborting run". RESET;
++    Stats \%total;
++    exit;
++  } else {
++    display "Continuing...";
++    $skip = 0;
++  } # if
++  
++  return;
++} # Interrupted
++
++sub workerDeath {
++  while ((my $worker = waitpid (-1, WNOHANG)) > 0) {
++    my $status  = $?;
++
++    # Ignore all child deaths except for processes we started
++    next if !exists $workerStatuses{$worker};
++
++    $workerStatuses{$worker} = $status;
++  } # while
++
++  $SIG{CHLD} = \&workerDeath;
++  
++  return;
++} # workerDeath
++
++sub execute ($$;$) {
++  my ($cmd, $host, $prompt) = @_;
++
++  my ($remoteHost, @lines);
++
++  # Mark $currentHost for interrupt
++  $currentHost = $host;
++  
++  # Start a log...
++  $log = Logger->new (name => $host) if $opts{log};
++  
++  verbose_nolf "Connecting to machine $host...";
++
++  display_nolf YELLOW . "$host:" . RESET;
++
++  eval {
++    $remoteHost = Rexec->new (
++      host   => $host,
++      prompt => $prompt,
++    );
++  };
++
++  # Problem with creating Rexec object. Log error if logging and return.
++  if ($@ || !$remoteHost) {
++    if ($opts{log}) {
++      $log->err ("Unable to connect to $host to execute command: $cmd") if $opts{log};
++    } else {
++      display RED . 'ERROR:' . RESET . " Unable to connect to $host to execute command: $cmd";
++    } # if
++
++    $total{ConnectFailures}++;
++
++    return (1, ());
++  } # if
++
++  verbose " connected";
++
++  display UNDERLINE . "$cmd" . RESET unless $opts{quiet};
++
++  @lines = $remoteHost->execute ($cmd);
++
++  if ($skip) {
++    # Kick current connection
++    kill INT => $remoteHost->{handle}->pid;
++  } # if
++
++#  if ($opts{parallel} != 0) {
++#    $log->err ("Unable to connect to $host to execute command\n$cmd") if $opts{log};
++#
++#    $total{ConnectFailures}++;
++#  } # if
++
++  verbose "Disconnected from $host";
++
++  my $status = $remoteHost->status;
++
++  return ($status, @lines);
++} # execute
++
++sub parallelize ($%) {
++  my ($cmd, %machines) = @_;
++
++  my $thread_count = 1;
++
++  foreach my $host (sort keys %machines) {
++    if ($thread_count <= $opts{parallel}) {
++      debug "Processing $host ($thread_count)";
++      $thread_count++;
++
++      if (my $pid = fork) {
++        # In parent process - record this host and its status
++        $workerNames{$pid} = $host;
++      } else {
++        # In spawned child...
++        $pid = $$;
++
++        debug "Starting process for $host [$pid]";
++
++        $workerNames{$pid} = $host;
++        
++        # Mark currentHost for interrupt (How does this work in the presence
++        # of parallelization?).
++        $currentHost = $host;
++       
++        my ($status, @lines) = execute $cmd, $host, $machines{$host};
++
++        $log = Logger->new (name => $host);
++
++        $log->log ($_) foreach (@lines);
++
++        exit $status;
++      } # if
++    } else {
++      # Wait for somebody to finish;
++      debug "Waiting for somebody to exit...";
++      my $reaped = wait;
++
++      debug "Reaped $workerNames{$reaped} [$reaped] (Status: $?)";
++      $workerStatuses{$reaped} = $? >> 8 if $reaped != -1;
++
++      $thread_count--;
++    } # if
++  } # foreach
++
++  # Wait for all kids
++  my %threads = %workerNames;
++
++  foreach (keys %threads) {
++    if (waitpid ($_, 0) == -1) {
++      delete $threads{$_};
++    } else {
++      $workerStatuses{$_} = $? >> 8;
++      debug "$threads{$_} [$_] exited with a status of $workerStatuses{$_}";
++    } # if
++  } # foreach
++
++  debug "All processed completed - Status:";
++
++  if (get_debug) {
++    foreach (sort keys %workerStatuses) {
++      debug "$workerNames{$_}\t[$_]:\tStatus: $workerStatuses{$_}";
++    } # foreach
++  } # if
++
++  # Gather output...
++  display "Output of all executions";
++  foreach my $host (sort keys %machines) {
++    if (-f "$host.log") {
++      display "$host:$_" foreach (ReadFile ("$host.log"));
++
++      #unlink "$_host.log";
++    } else {
++      warning "Unable to find output for $host ($host.log missing)";
++    } # if
++  } # foreach
++  
++  return;
++} # parallelize
++
++# Print the totals if interrupted
++$SIG{INT} = \&Interrupted;
++
++# Get our options
++GetOptions (
++  \%opts,
++  'usage',
++  'help',
++  'verbose',
++  'debug',
++  'log',
++  'quiet',
++  'type=s',
++  'parallel=i',
++);
++
++my $cmd = join ' ', @ARGV;
++
++pod2usage ('No command specified') unless $cmd;
++
++my $machines = Clearadm->new;
++
++if ($opts{parallel} > 0) {
++  #parallelize ($cmd, %machines);
++  Stats \%total;
++  exit;
++} # if
++
++display "NOTE: Logging outputs to <host>.log" if $opts{log};
++
++my $condition = $opts{type} ? "type=$opts{type}" : '';
++
++foreach ($machines->SearchSystem ($condition)) {
++  my %system = %$_;
++  $total{Machines}++;
++
++  my ($status, @lines) = execute $cmd, $system{name};
++
++  if ($skip) {
++    $skip = 0;
++    next;
++  } # if
++
++  if (defined $status) {
++    if ($status == 0) {
++      $total{Executions}++;
++    } else {
++      $total{Failures}++;
++
++      next;
++    } # if
++  } # if
++
++  if ($opts{log}) {
++    $log->log ($_) foreach (@lines);
++  } else {
++    display $_ foreach (@lines);
++  } # if
++} # foreach
++
++Stats \%total;
diff --cc bin/test.py
index 0000000,0000000..f317064
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,98 @@@
++#!/usr/bin/python
++
++import sys, getopt
++
++security_logfile = '/var/log/auth.log'
++verbose = 0
++debug   = 0
++update  = 0
++email   = 0
++
++def Usage (msg = ''):
++  if msg != '':
++    print msg
++    
++  print """
++Usage: bice.py [-u|sage] [-v|erbose] [-d|ebug] [-nou|pdate] [-nom|ail]
++               [-f|ilename <filename> ]
++
++Where:
++  -u|sage     Print this usage
++  -v|erbose:  Verbose mode (Default: -verbose)
++  -nou|pdate: Don't update security logfile file (Default: -update)
++  -nom|ail:   Don't send emails (Default: -mail)
++  -f|ilename: Open alternate messages file (Default: /var/log/auth.log)
++  """
++def mainold (argv):
++  global verbose, debug, update, email, security_logfile
++  
++  print "in main"
++  
++  try:
++    #opts, args = getopt.getopt (argv, "vd", ['verbose', 'debug', 'usage', 'update', 'mail', 'file='])
++    opts, args = getopt.getopt (argv, "hi:o:", ["ifile=","ofile="])
++  except getopt.GetoptError:
++    Usage;
++    sys.exit (1);
++    
++  for opt, arg in opts:
++    print 'opt: ', opt
++    print 'arg:',  arg
++     
++    if opt in ['-v', '-verbose']:
++      verbose = 1
++    elif opt in ['-d', '-debug']:
++      debug = 1
++    elif opt in ['-u', '-usage']:
++      Usage 
++    elif opt in ['-update']:
++      update = 1
++    elif opt in ['-m', '-mail']:
++      email = 1
++    elif opt in ['-f', '-file']:
++      security_logfile = arg
++  
++  print 'Args:'
++  print 'verbose', verbose
++  print 'debug',   debug
++  print 'update',  update
++  print 'email',   email
++  print 'file',    security_logfile
++  
++def main(argv):
++  global verbose, debug, update, email, security_logfile
++
++  inputfile = ''
++  outputfile = ''
++
++  try:
++    opts, args = getopt.getopt(argv,"hvi:o:",["verbose", "ifile=","ofile="])
++  except getopt.GetoptError:
++    Usage ()
++    print 'test.py -i <inputfile> -o <outputfile>'
++    sys.exit(2)
++    
++  for opt, arg in opts:
++    print 'opt: ', opt
++    print 'arg: ', arg
++    if opt in ['-v', '--verbose']:
++      verbose = 1
++    elif opt in ['-u', '-usage']:
++      Usage ()
++    elif opt == '-h':
++      print 'test.py -i <inputfile> -o <outputfile>'
++      sys.exit()
++    elif opt in ("-i", "--ifile"):
++      inputfile = arg
++    elif opt in ("-o", "--ofile"):
++      outputfile = arg
++
++  print 'Args:'
++  print 'verbose', verbose
++  print 'debug',   debug
++  print 'update',  update
++  print 'email',   email
++  print 'file',    security_logfile
++
++if __name__ == "__main__":
++   main (sys.argv[1:])
diff --cc maps/test.msg
index 0000000,0000000..fe92463
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,171 @@@
++Message-ID: <546412AB.7090404@DeFaria.com>\r
++Date: Wed, 12 Nov 2014 18:08:43 -0800\r
++From: Andrew DeFaria <Andrew@DeFaria.com>\r
++User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0\r
++MIME-Version: 1.0\r
++To: Yubico Support <support@yubico.com>\r
++Subject: Glutten for punishment...\r
++Content-Type: multipart/alternative;\r
++ boundary="------------060602060101040803010204"\r
++\r
++This is a multi-part message in MIME format.\r
++--------------060602060101040803010204\r
++Content-Type: text/plain; charset=utf-8; format=flowed\r
++Content-Transfer-Encoding: 7bit\r
++\r
++OK I returned the Yubico Security key thing and bought the Yubikey Neo. \r
++I'm on Windows 7 with Chrome  38.0.2125.111 m. I even have the FIDO U2F \r
++(Universal 2nd Factor) extension 0.9.3 installed.\r
++\r
++I go to http://demo.yubico.com/start/u2f/neo?tab=register and insert my \r
++key. Unlike the instructions my yubikey is not a "flashing U2F device" - \r
++the light is on solid. I hit the button anyway. It does nothing but \r
++eventually times out with:\r
++\r
++\r
++        Registration failed!\r
++\r
++    Make sure you have a U2F device connected, and try again.\r
++\r
++      Traceback (most recent call last):\r
++       File "/root/python-u2flib-server-demo/examples/yubiauth_server.py", line 159, in __call__\r
++         raise Exception("FIDO Client error: %s" % error)\r
++    Exception: FIDO Client error: 5 (TIMEOUT)\r
++      \r
++\r
++/root? Really?\r
++\r
++Similarly when I go to my Google account under Security Keys and follow \r
++the instruction there the yubikey doesn't do anything! When I tap the \r
++gold circle the light goes out for a brief second then back on. But the \r
++"Now insert (and tap) your Security Key" with the spinning progress \r
++indicator goes forever...\r
++\r
++Now what?\r
++-- \r
++Andrew DeFaria <http://defaria.com>\r
++ClearSCM, Inc. <http://clearscm.com>\r
++\r
++--------------060602060101040803010204\r
++Content-Type: text/html; charset=utf-8\r
++Content-Transfer-Encoding: 8bit\r
++\r
++<html>\r
++  <head>\r
++\r
++    <meta http-equiv="content-type" content="text/html; charset=utf-8">\r
++  </head>\r
++  <body style="background-color: rgb(255, 255, 255); color: rgb(0, 0,\r
++    0);" bgcolor="#FFFFFF" text="#000000">\r
++    OK I returned the Yubico Security key thing and bought the Yubikey\r
++    Neo. I'm on Windows 7 with Chrome  38.0.2125.111 m. I even have the\r
++    FIDO U2F (Universal 2nd Factor) extension 0.9.3 installed. <br>\r
++    <br>\r
++    I go to <a class="moz-txt-link-freetext" href="http://demo.yubico.com/start/u2f/neo?tab=register">http://demo.yubico.com/start/u2f/neo?tab=register</a> and insert\r
++    my key. Unlike the instructions my yubikey is not a "flashing U2F\r
++    device" - the light is on solid. I hit the button anyway. It does\r
++    nothing but eventually times out with:<br>\r
++    <blockquote>\r
++      <h2 style="margin: 10px 0px; font-family: 'Helvetica Neue',\r
++        Helvetica, Arial, sans-serif; font-weight: bold; line-height:\r
++        40px; color: rgb(51, 51, 51); text-rendering:\r
++        optimizelegibility; font-size: 31.5px; font-style: normal;\r
++        font-variant: normal; letter-spacing: normal; orphans: auto;\r
++        text-align: start; text-indent: 0px; text-transform: none;\r
++        white-space: normal; widows: auto; word-spacing: 0px;\r
++        -webkit-text-stroke-width: 0px;">Registration failed!</h2>\r
++      <p style="margin: 0px 0px 10px; color: rgb(51, 51, 51);\r
++        font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\r
++        font-size: 18px; font-style: normal; font-variant: normal;\r
++        font-weight: 200; letter-spacing: normal; line-height: 30px;\r
++        orphans: auto; text-align: start; text-indent: 0px;\r
++        text-transform: none; white-space: normal; widows: auto;\r
++        word-spacing: 0px; -webkit-text-stroke-width: 0px;">Make sure\r
++        you have a U2F device connected, and try again.</p>\r
++      <pre style="padding: 9.5px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 13px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; display: block; margin: 0px 0px 10px; line-height: 20px; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); font-style: normal; font-variant: normal; font-weight: 200; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(245, 245, 245);"> Traceback (most recent call last):\r
++  File "/root/python-u2flib-server-demo/examples/yubiauth_server.py", line 159, in __call__\r
++    raise Exception("FIDO Client error: %s" % error)\r
++Exception: FIDO Client error: 5 (TIMEOUT)\r
++ </pre>\r
++    </blockquote>\r
++    <div class="moz-signature">/root? Really?<br>\r
++      <br>\r
++      Similarly when I go to my Google account under Security Keys and\r
++      follow the instruction there the yubikey doesn't do anything! When\r
++      I tap the gold circle the light goes out for a brief second then\r
++      back on. But the "Now insert (and tap) your Security Key" with the\r
++      spinning progress indicator goes forever...<br>\r
++      <br>\r
++      Now what?<br>\r
++      -- <br>\r
++      <style type="text/css">\r
++body {\r
++  font:                       Helvetica, Arial, sans-serif;\r
++}\r
++p {\r
++  font:                       Helvetica, Arial, sans-serif;\r
++}\r
++.standout {\r
++  font-family:                verdana,\r
++                      arial,\r
++                      sans-serif;\r
++  font-size:          12px;\r
++  color:              #993333;\r
++  line-height:                13px;\r
++  font-weight:                bold;\r
++  margin-bottom:      10px;\r
++}\r
++.code {\r
++  border-top:         1px solid #ddd;\r
++  border-left:                1px solid #ddd;\r
++  border-right:               2px solid #000;\r
++  border-bottom:      2px solid #000;\r
++  padding:            10px;\r
++  margin-top:         5px;\r
++  margin-left:                5%;\r
++  margin-right:               5%;\r
++  background:         #ffffea;\r
++  color:              black;\r
++  font-family:                courier;\r
++  white-space:                pre;\r
++  -moz-border-radius: 10px;\r
++}\r
++.terminal {\r
++  border-top:         10px solid #03f;\r
++  border-left:                1px solid #ddd;\r
++  border-right:               2px solid grey;\r
++  border-bottom:      2px solid grey;\r
++  padding:            10px;\r
++  margin-top:         5px;\r
++  margin-left:                5%;\r
++  margin-right:               5%;\r
++  background:         black;\r
++  color:              white;\r
++  font-family:                courier;\r
++  white-space:                pre;\r
++  -moz-border-radius: 10px;\r
++}\r
++a:link { \r
++  color:              blue;\r
++}\r
++\r
++a:visited {\r
++  color:              darkblue;\r
++}\r
++\r
++a:hover { \r
++  color:              black;\r
++  background-color:   #ffffcc;\r
++  text-decoration:    underline;\r
++}\r
++\r
++a:active { \r
++  color:              red;\r
++}\r
++</style><a href="http://defaria.com">Andrew DeFaria</a><br>\r
++      <a href="http://clearscm.com">ClearSCM, Inc.</a><br>\r
++    </div>\r
++  </body>\r
++</html>\r
++\r
++--------------060602060101040803010204--\r
diff --cc maps/test.pl
index 0000000,0000000..0310205
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,42 @@@
++#!/usr/bin/perl
++use strict;
++use warnings;
++
++use lib "/opt/clearscm/lib";
++
++use Display;
++use Utils;
++use Net::SMTP;
++
++my %config = (
++  SMTPHOST => 'defaria.com',
++);
++
++sub DeliverMsg ($) {
++  my ($msg) = @_;
++  
++  my $smtp = Net::SMTP->new ($config{SMTPHOST})
++    or error "Unable to connect to mail server: $config{SMTPHOST}", 1;
++  
++  $smtp->mail ('Andrew@DeFaria.com');
++  
++  $smtp->to ('adefaria@gmail.com');
++  
++  $smtp->data;
++  $smtp->datasend ('From: Andrew@DeFaria.com');
++  $smtp->datasend ('To: adefaria@gmail.com');
++  $smtp->datasend ('Subject: Forwarded mail');
++  $smtp->datasend ('Content-Type: plain/text');
++  $smtp->datasend ("\n");
++  $smtp->datasend ($msg);
++  $smtp->dataend;
++  $smtp->quit;
++  
++  return;    
++} # DeliverMsg
++
++my $msg = ReadFile 'test.msg';
++
++DeliverMsg ($msg);
++
++display 'done';
diff --cc rc/sshconfig
@@@ -9,10 -10,32 +10,33 @@@ Host 
  Host home
    Hostname defaria.com
    User andrew
- Host defaria.com
-   User andrew
    IdentityFile                ~/.ssh/id_ecdsa
+  
+ Host gerrit-rtp
+   Hostname gerrit-ccxsw.rtp.broadcom.com
+   User svcccxswgit
  
- Host *
-   User adefaria
+ Host vdi
+   Hostname sjrvda0482.sjs.avagotech.net
+ Host eca-rtp-02
+   Hostname eca-rtp-02.rtp.broadcom.com
+   User ccxswbuild
+ Host eca-rtp-04
+   Hostname eca-rtp-04.rtp.broadcom.com
+   User ccxswbuild
+ Host git-ric
+   Hostname git-ccxsw.ric.broadcom.com
+   #User svcccxswgit
+   User ccxswbuild
+ Host git-rtp
+   Hostname git-ccxsw.rtp.broadcom.com
+   #User svcccxswgit
+   User ccxswbuild
+   
+ Host jira-dev
+   Hostname jira-rtp-06.rtp.broadcom.com
++>>>>>>> 9956e403ab89bc984faf9cb22a8860a34c310ac7
diff --cc test/test.py
index 0000000,0000000..981ea9b
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++#!/usr/bin/env python
++a, b = 0, 1
++
++while b < 100:
++  print b
++  a, b = b, a+b
++    
++print "done"
++
++quit()