From: Jon Langseth Date: Wed, 25 Jan 2012 19:11:41 +0000 (+0100) Subject: Adding the first few local CLI-clients as examples X-Git-Url: https://git.defcon.no/?p=hermes;a=commitdiff_plain;h=26723586ae1875f592470e77629924081e369996 Adding the first few local CLI-clients as examples --- diff --git a/guc-clients/add_apikey.pl b/guc-clients/add_apikey.pl new file mode 100755 index 0000000..a543c23 --- /dev/null +++ b/guc-clients/add_apikey.pl @@ -0,0 +1,146 @@ +#!/usr/bin/perl + +use strict; +use LWP; +use Data::Dumper; +use JSON; +use Getopt::Long; +use AppConfig; + +my $help = 0; +my $host_ip = ""; +my $level = ""; +my $keyfile =""; +my $api_base = ""; +my $api_key = ""; +my $configfile; + +my $config = AppConfig->new( { CREATE => 1 } ); + +$config->define("api_url=s"); +$config->define("api_keyfile=s"); + +GetOptions( + "help" => \$help, + "host=s" => \$host_ip, + "access=s" => \$level, + "configfile=s" => \$configfile, +); + +if ( + (not $configfile) || + (( $configfile ) && ( not -f $configfile )) +) +{ + $help = 1; +} +else +{ + $config->file( $configfile ); + $api_base = $config->api_url; + $keyfile = $config->api_keyfile; +} +if ( + ( ( $level ne "limited_read" ) && + ( $level ne "full_read" ) && + ( $level ne "read_write" ) ) || + ( not $api_base ) || + ( not $api_base =~ m/^http:\/\/\w+/ ) || + ( not $keyfile ) || + ( not -f $keyfile ) +) { + $help = 1; +} + +if ( $help ) +{ + print < ); +close KEY; + +my ($g_ua, $session, $auth_key, $data); + +$g_ua = LWP::UserAgent->new; +$g_ua->cookie_jar({}); # In-memory jar, look at HTTP::Cookies for persistant + +login_apikey(); + +$data = exec_apinode('auth/new_apikey', { 'host_ip' => $host_ip, 'access' => $level }); +print Dumper($data); +undef $data; + +logout(); +################################################################################################ +sub exec_apinode($$) +{ + my $node = shift; + my $param = shift; + + my ( $response, $data ); + + $session = "" if not defined $session; + $auth_key = "" if not defined $auth_key; + my $url = $api_base . "/" . $node; + + $param->{'session'} = $session; + $param->{'auth_key'} = $auth_key; + + $response = $g_ua->post( $url, $param ); + if ( $response->is_success ) + { + if ( $response->content =~ m/\s*{/ ) + { + $data = decode_json( $response->content); + } + else + { + $data = $response->content; + } + + } + return $data; +} + +sub login_apikey +{ + my $response = $g_ua->post( $api_base . "/auth/login", + [ "api_key" => $api_key ] ); + + my $data = decode_json( $response->content) if $response->is_success; + die("HTTP error") unless $response->is_success; + + if ( $data->{'response'} eq "ok" ) + { + $session = $data->{'session'}; + $auth_key = $data->{'auth_key'}; + } + else + { + exit; + } + undef $data; undef $response; +} + +sub logout +{ + my $response = $g_ua->post( $api_base . "/auth/logout", + [ "session" => $session ] ); + die("HTTP error") unless $response->is_success; + undef $session; undef $auth_key; +} diff --git a/guc-clients/assignphone b/guc-clients/assignphone new file mode 100755 index 0000000..074ab1f --- /dev/null +++ b/guc-clients/assignphone @@ -0,0 +1,176 @@ +#!/usr/bin/perl +use strict; + +use Getopt::Long; +use Net::LDAP; +use Net::LDAP::Control::Paged; +use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); +use LWP; +use JSON; +use AppConfig; + +my $api_key; + +my $help; +my $username; +my $configfile; +my ($g_ua, $session, $api_key, $auth_key, $data, $domain); +my ($user, $sipuser, $mac); + +my $config = AppConfig->new({ CREATE => 1 }); + +$config->define("api_url=s"); +$config->define("api_keyfile=s"); + +GetOptions( + "help" => \$help, + "macaddress=s" => \$mac, + "username=s" => \$username, + "configfile=s" => \$configfile, +); + +if ( + (not $username) || + (not $mac) || + (( $configfile ) && ( not -f $configfile )) +) +{ + $help = 1; +} + +$config->file( $configfile ); + +if ( ( not $config->api_url ) || + ( not $config->api_keyfile ) || + ( $config->api_keyfile && not -f $config->api_keyfile ) ) +{ + $help = 1; +} + +if ( $help ) { +print <api_keyfile; +chomp( $api_key = ); +close KEY; + +if ( not $username =~ m/\w+/ ) +{ print "Illegal username\n"; exit; } + +# Do stuff to the MAC adress. +$mac =~ s/[:-]//g if ( $mac =~ m/((?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2})/i); +$mac = lc $mac; +if ( not $mac =~ m/^[a-f0-9]{12}/ ) +{ + printf("Malformed MAC adress.\n"); + exit; +} + +$g_ua = LWP::UserAgent->new; +$g_ua->cookie_jar({}); # In-memory jar, look at HTTP::Cookies for persistant + +login_apikey(); + +# First: fetch a supported domain from the API... +$data = exec_apinode("domain/list", undef); +if ( $data->{'response'} eq 'ok' ) +{ + $domain = $data->{'list'}[0]; +} +else +{ + printf("Unable to get domain name. Aborting\n"); + logout(); + exit; +} +$sipuser = $username . '@' . $domain; + +$data = exec_apinode("user/get", { 'user' => $sipuser }); +if ( not $data->{'response'} eq 'ok' ) +{ + printf("Failed to verify that user exists. Aborting\n"); + logout(); + exit; +} + +$data = exec_apinode("phone/add", { 'user' => $sipuser, 'mac' => $mac }); + +printf("Failed to add phone+user, cause given: '%s'\n", $data->{'cause'}) + if ( not $data->{'response'} eq 'ok' ); + +printf("Assigned phone with mac '%s' to user '%s'\n", $mac, $sipuser) + if ( $data->{'response'} eq 'ok' ); + +logout(); +################################################################################################ +sub exec_apinode($$) +{ + my $node = shift; + my $param = shift; + + my ( $response, $data ); + + $session = "" if not defined $session; + $auth_key = "" if not defined $auth_key; + my $url = $config->api_url . "/" . $node; + + $param->{'session'} = $session; + $param->{'auth_key'} = $auth_key; + + $response = $g_ua->post( $url, $param ); + if ( $response->is_success ) + { + if ( $response->content =~ m/\s*{/ ) + { + $data = decode_json( $response->content); + } + else + { + $data = $response->content; + } + + } + return $data; +} + +sub login_apikey +{ + my $response = $g_ua->post( $config->api_url . "/auth/login", + [ "api_key" => $api_key ] ); + + my $data = decode_json( $response->content) if $response->is_success; + die("HTTP error") unless $response->is_success; + + if ( $data->{'response'} eq "ok" ) + { + $session = $data->{'session'}; + $auth_key = $data->{'auth_key'}; + } + else + { + print "Unable to log in to Hermes API\n"; + exit; + } + undef $data; undef $response; +} + +sub logout +{ + my $response = $g_ua->post( $config->api_url . "/auth/logout", + [ "session" => $session ] ); + die("HTTP error") unless $response->is_success; + undef $session; undef $auth_key; +} diff --git a/guc-clients/feide2sipuser b/guc-clients/feide2sipuser new file mode 100755 index 0000000..48e20c8 --- /dev/null +++ b/guc-clients/feide2sipuser @@ -0,0 +1,285 @@ +#!/usr/bin/perl +use strict; + +use Getopt::Long; +use Net::LDAP; +use Net::LDAP::Control::Paged; +use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); +use LWP; +use JSON; +use AppConfig; + +my $api_key; + +my $help; +my $username; +my $configfile; +my ($g_ua, $session, $api_key, $auth_key, $data, $domain); +my ($user, $displayname, $phone, $mail, $sipuser, $linetext); + +my $config = AppConfig->new({ CREATE => 1 }); + +$config->define("api_url=s"); +$config->define("api_keyfile=s"); +$config->define("feide_server=s"); +$config->define("feide_login=s"); +$config->define("feide_passwd=s"); +$config->define("feide_people=s"); + +$config->define("numbers_local_prefix=s"); +$config->define("numbers_local_series=s"); +$config->define("numbers_countrycode=s"); + +GetOptions( + "help" => \$help, + "username=s" => \$username, + "configfile=s" => \$configfile, +); + +if ( + (not $username) || + (( $configfile ) && ( not -f $configfile )) +) +{ + $help = 1; +} + +$config->file( $configfile ); + +if ( ( not $config->api_url ) || + ( not $config->api_keyfile ) || + ( $config->api_keyfile && not -f $config->api_keyfile ) || + ( not $config->feide_server ) || + ( not $config->feide_login ) || + ( not $config->feide_passwd ) || + ( not $config->feide_people ) ) +{ + $help = 1; +} + +if ( $help ) { +print <api_keyfile; +chomp( $api_key = ); +close KEY; + +if ( not $username =~ m/\w+/ ) +{ print "Illegal username\n"; exit; } + + +# Kobler til LDAP-server +my $ldap = Net::LDAP->new($config->feide_server, version => 3) + or die "Can't connect to LDAP server: " . $config->feide_server . "!\n"; +my $msg = $ldap->bind (dn => $config->feide_login, password => $config->feide_passwd); +if ( $msg->code()) { + die ("LDAP error: ", $msg->error_text((), "\n")); +} + +$msg = $ldap->search( base => $config->feide_people, + scope => "subtree", + filter => "(uid=". $username .")", + attrs => () ); +die("Getting information for " . $username . " failed..." ) if ( $msg->count != 1 ); + +$user = $msg->entry; +$displayname = $user->get_value("displayName"); +$phone = $user->get_value("telephoneNumber"); +$mail = $user->get_value("mail"); +$sipuser = $user->get_value("eduPersonPrincipalName"); + +my $short_test = "^" . $config->numbers_local_series; +my $long_test = "^" . $config->numbers_local_prefix . $config->numbers_local_series; + +if ( $phone =~ m/$short_test/ ) +{ + print "Phone number is in 5-digit local format. Completing E164.\n"; + $linetext = $config->numbers_local_prefix . $phone; + $phone = $config->numbers_countrycode . $config->numbers_local_prefix . $phone; +} +elsif ( $phone =~ m/$long_test/ ) +{ + print "Phone number is in 8-digit local format. Adding CC.\n" ; + $linetext = $phone; + $phone = $config->numbers_countrycode . $phone; +} +else +{ + print "Unable to recognize Phone number. Check FEIDE\n"; + exit; +} + +print "Data so far:" . "\n"; +print " Username: " . $username . "\n"; +print " Displayname: " . $displayname . "\n"; +print " Phone: " . $phone . "\n"; +print " Line-text: " . $linetext . "\n"; +print " Mail: " . $mail . "\n"; +print " SIP address: " . $sipuser . "\n"; + +$msg = $ldap->unbind; +if ( $msg->code()) { die ("LDAP error: ", $msg->error_text((), "\n")); } + +$g_ua = LWP::UserAgent->new; +$g_ua->cookie_jar({}); # In-memory jar, look at HTTP::Cookies for persistant + +login_apikey(); + +$data = exec_apinode("user/available", { "user" => $sipuser }); +if ( not $data->{'response'} eq 'ok' ) +{ + printf("Unable to add user, Hermes response to available query is: %s\n", $data->{'cause'}); + exit; +} +undef $data; + +$data = exec_apinode("user/add_local", { + "user" => $sipuser, + "displayname" => $displayname, + "email" => $mail, +}); +if ( not $data->{'response'} eq 'ok' ) +{ + printf("Unable to add user, Hermes response to add_local query is: %s\n", $data->{'cause'}); + exit; +} +else +{ + printf("Added user, login information:\n"); + printf("username: %s@%s\nauthid: %s\npassword: %s\n" . + "registrar: %s:%d\nproxy: %s:%d\ndisplayname: %s\n" . + "email: %s\npermission: %s\n", + $data->{'user'}->{'username'}, + $data->{'user'}->{'domain'}, + $data->{'user'}->{'authid'}, + $data->{'user'}->{'password'}, + $data->{'user'}->{'registrar'}, + $data->{'user'}->{'r_port'}, + $data->{'user'}->{'proxy'}, + $data->{'user'}->{'p_port'}, + $data->{'user'}->{'displayname'}, + $data->{'user'}->{'email'}, + $data->{'user'}->{'permittedcalls'}, + ); + $domain = $data->{'user'}->{'domain'}, + $phone .= "\@" . $domain; +} +undef $data; + +unless ( $mail eq $sipuser ) +{ + $data = exec_apinode("alias/add", { + "destination" => $sipuser, + "alias" => $mail, + }); + if ( not $data->{'response'} eq 'ok' ) + { + printf("Unable to add alias, Hermes response to add_local query is: %s\n", $data->{'cause'}); + printf("Attempting to roll back user %s: ", $sipuser); + undef $data; $data = exec_apinode("user/remove", { "user" => $sipuser }); + printf("%s\n", $data->{'response'}); + exit; + } + else + { printf("alias: %s\n", $mail); } + undef $data; +} + +$data = exec_apinode("alias/add", { + "destination" => $sipuser, + "alias" => $phone, +}); +if ( not $data->{'response'} eq 'ok' ) +{ + printf("Unable to add E164 number, Hermes response to add_local query is: %s\n", $data->{'cause'}); + printf("Attempting to roll back user %s: ", $sipuser); + exec_apinode("alias/remove", { "alias" => $mail }); + exec_apinode("user/remove", { "user" => $sipuser }); + exit; +} +else +{ printf("e164: %s\n", $phone); } +undef $data; + +$data = exec_apinode("user/update", { + "user" => $sipuser, + "linetext" => $linetext, +}); +if ( not $data->{'response'} eq 'ok' ) +{ + printf("Did not update 'linetext' element."); +} + +# During testing: +#exec_apinode("alias/remove", { "alias" => $mail }); +#exec_apinode("alias/remove", { "alias" => $phone }); +#exec_apinode("user/remove", { "user" => $sipuser }); + +logout(); +################################################################################################ +sub exec_apinode($$) +{ + my $node = shift; + my $param = shift; + + my ( $response, $data ); + + $session = "" if not defined $session; + $auth_key = "" if not defined $auth_key; + my $url = $config->api_url . "/" . $node; + + $param->{'session'} = $session; + $param->{'auth_key'} = $auth_key; + + $response = $g_ua->post( $url, $param ); + if ( $response->is_success ) + { + if ( $response->content =~ m/\s*{/ ) + { + $data = decode_json( $response->content); + } + else + { + $data = $response->content; + } + + } + return $data; +} + +sub login_apikey +{ + my $response = $g_ua->post( $config->api_url . "/auth/login", + [ "api_key" => $api_key ] ); + + my $data = decode_json( $response->content) if $response->is_success; + die("HTTP error") unless $response->is_success; + + if ( $data->{'response'} eq "ok" ) + { + $session = $data->{'session'}; + $auth_key = $data->{'auth_key'}; + } + else + { + print "Unable to log in to Hermes API\n"; + exit; + } + undef $data; undef $response; +} + +sub logout +{ + my $response = $g_ua->post( $config->api_url . "/auth/logout", + [ "session" => $session ] ); + die("HTTP error") unless $response->is_success; + undef $session; undef $auth_key; +} diff --git a/guc-clients/sample_config b/guc-clients/sample_config new file mode 100644 index 0000000..a419e40 --- /dev/null +++ b/guc-clients/sample_config @@ -0,0 +1,14 @@ +[api] +url = http://server.example.com/hermes/api +keyfile = sample_keyfile + +[feide] +server = ldaps://feide.example.com +login = uid=ldapread,ou=ldapusers,dc=example,dc=com +passwd = V3ry$ec37 +people = ou=people,dc=example,dc=com + +[numbers] +countrycode = +47 +local_prefix = 734 +local_series = 114[69]\d diff --git a/guc-clients/sample_keyfile b/guc-clients/sample_keyfile new file mode 100644 index 0000000..f3cce0e --- /dev/null +++ b/guc-clients/sample_keyfile @@ -0,0 +1 @@ +4hErgw3QFJLeuXGW