git.fiddlerwoaroof.com
Browse code

Merge pull request #1 from cjdev/otp-code

CJPM-5223: add code for generating TOTP tokens

Ed Langley authored on 30/05/2017 23:10:39
Showing 15 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+root = true
2
+
3
+[*]
4
+charset = utf-8
5
+end_of_line = lf
6
+insert_final_newline = true
7
+trim_trailing_whitespace = true
8
+
9
+[*.{cc,h}]
10
+indent_style = space
11
+indent_size = 4
... ...
@@ -20,3 +20,4 @@ dual_control
20 20
 .idea
21 21
 Vagrantfile
22 22
 
23
+core
... ...
@@ -1,10 +1,10 @@
1 1
 sudo: required
2 2
 dist: trusty
3 3
 install:
4
-  - sudo apt-get install libpam0g-dev
4
+  - sudo apt-get install libpam0g-dev libssl-dev
5 5
 language: cpp
6 6
 notifications:
7 7
   email:
8 8
     on_success: change
9 9
     on_failure: change
10
-script: ./configure && make test
10
+script: ./configure && make -k test
... ...
@@ -1,10 +1,10 @@
1
-CXXFLAGS += -fPIC -fno-stack-protector -std=c++11
2
-CFLAGS += -fPIC -fno-stack-protector
3
-LDFLAGS = -lpam
1
+CXXFLAGS += -fPIC -fno-stack-protector -std=c++11  -g
2
+CFLAGS += -fPIC -fno-stack-protector -g
3
+LDFLAGS = -lpam @LIBS@
4 4
 
5 5
 INTEGRATION_OBJS = sys_syslog.o sys_fstream.o sys_unistd.o sys_pwd.o sys_pam.o \
6 6
                    sys_stdlib.o sys_time.o
7
-OBJS = dual_control.o request.o validator.o conversation.o user.o token.o logger.o session.o installer.o system.o
7
+OBJS = dual_control.o request.o validator.o conversation.o user.o token.o logger.o session.o installer.o system.o generator.o
8 8
 TEST_SOURCES := $(wildcard *_test.cc)
9 9
 TESTS := $(patsubst %.cc,%.out,$(TEST_SOURCES))
10 10
 TESTRUNS := $(patsubst %.out,RUN_%,$(TESTS))
... ...
@@ -26,7 +26,7 @@ dual_control.a: dual_control.o dual_control_integrate.o $(OBJS) $(INTEGRATION_OB
26 26
 	ranlib $@
27 27
 
28 28
 dual_control: dual_control_tool.o $(OBJS) $(INTEGRATION_OBJS)
29
-	$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)  -o $@ $^
29
+	$(CXX) $(CXXFLAGS) $(CPPFLAGS)  -o $@ $^ $(LDFLAGS)
30 30
 
31 31
 
32 32
 .PHONY: clean
... ...
@@ -46,7 +46,7 @@ distclean: clean
46 46
 -include .depend
47 47
 
48 48
 %_test.out: %_test.o $(OBJS)
49
-	$(CXX) $(CXXFLAGS) $(CPPFLAGS)  -o $@ $^
49
+	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $^ $(LDFLAGS)
50 50
 
51 51
 RUN_%: %.out
52 52
 	@echo running $<
... ...
@@ -70,5 +70,3 @@ endif
70 70
 .PHONY: format
71 71
 format:
72 72
 	@./format.sh *.cc *.h
73
-
74
-
... ...
@@ -197,7 +197,8 @@ test -x / || exit 1"
197 197
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
198 198
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
199 199
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
200
-  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
200
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
201
+test \$(( 1 + 1 )) = 2 || exit 1"
201 202
   if (eval "$as_required") 2>/dev/null; then :
202 203
   as_have_required=yes
203 204
 else
... ...
@@ -585,8 +586,47 @@ PACKAGE_BUGREPORT='BUG-REPORT-ADDRESS'
585 586
 PACKAGE_URL=''
586 587
 
587 588
 ac_unique_file="config.h.in"
589
+# Factoring default headers for most tests.
590
+ac_includes_default="\
591
+#include <stdio.h>
592
+#ifdef HAVE_SYS_TYPES_H
593
+# include <sys/types.h>
594
+#endif
595
+#ifdef HAVE_SYS_STAT_H
596
+# include <sys/stat.h>
597
+#endif
598
+#ifdef STDC_HEADERS
599
+# include <stdlib.h>
600
+# include <stddef.h>
601
+#else
602
+# ifdef HAVE_STDLIB_H
603
+#  include <stdlib.h>
604
+# endif
605
+#endif
606
+#ifdef HAVE_STRING_H
607
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
608
+#  include <memory.h>
609
+# endif
610
+# include <string.h>
611
+#endif
612
+#ifdef HAVE_STRINGS_H
613
+# include <strings.h>
614
+#endif
615
+#ifdef HAVE_INTTYPES_H
616
+# include <inttypes.h>
617
+#endif
618
+#ifdef HAVE_STDINT_H
619
+# include <stdint.h>
620
+#endif
621
+#ifdef HAVE_UNISTD_H
622
+# include <unistd.h>
623
+#endif"
624
+
588 625
 ac_subst_vars='LTLIBOBJS
589 626
 LIBOBJS
627
+EGREP
628
+GREP
629
+CPP
590 630
 PAM_MODULE_DIRECTORY
591 631
 OBJEXT
592 632
 EXEEXT
... ...
@@ -645,7 +685,8 @@ CC
645 685
 CFLAGS
646 686
 LDFLAGS
647 687
 LIBS
648
-CPPFLAGS'
688
+CPPFLAGS
689
+CPP'
649 690
 
650 691
 
651 692
 # Initialize some variables set by options.
... ...
@@ -1266,6 +1307,7 @@ Some influential environment variables:
1266 1307
   LIBS        libraries to pass to the linker, e.g. -l<library>
1267 1308
   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
1268 1309
               you have headers in a nonstandard directory <include dir>
1310
+  CPP         C preprocessor
1269 1311
 
1270 1312
 Use these variables to override the choices made by `configure' or to help
1271 1313
 it to find libraries and programs with nonstandard names/locations.
... ...
@@ -1384,6 +1426,253 @@ fi
1384 1426
   as_fn_set_status $ac_retval
1385 1427
 
1386 1428
 } # ac_fn_c_try_compile
1429
+
1430
+# ac_fn_c_try_cpp LINENO
1431
+# ----------------------
1432
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
1433
+ac_fn_c_try_cpp ()
1434
+{
1435
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1436
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
1437
+case "(($ac_try" in
1438
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1439
+  *) ac_try_echo=$ac_try;;
1440
+esac
1441
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1442
+$as_echo "$ac_try_echo"; } >&5
1443
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
1444
+  ac_status=$?
1445
+  if test -s conftest.err; then
1446
+    grep -v '^ *+' conftest.err >conftest.er1
1447
+    cat conftest.er1 >&5
1448
+    mv -f conftest.er1 conftest.err
1449
+  fi
1450
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1451
+  test $ac_status = 0; } > conftest.i && {
1452
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
1453
+	 test ! -s conftest.err
1454
+       }; then :
1455
+  ac_retval=0
1456
+else
1457
+  $as_echo "$as_me: failed program was:" >&5
1458
+sed 's/^/| /' conftest.$ac_ext >&5
1459
+
1460
+    ac_retval=1
1461
+fi
1462
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1463
+  as_fn_set_status $ac_retval
1464
+
1465
+} # ac_fn_c_try_cpp
1466
+
1467
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
1468
+# -------------------------------------------------------
1469
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
1470
+# the include files in INCLUDES and setting the cache variable VAR
1471
+# accordingly.
1472
+ac_fn_c_check_header_mongrel ()
1473
+{
1474
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1475
+  if eval \${$3+:} false; then :
1476
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
1477
+$as_echo_n "checking for $2... " >&6; }
1478
+if eval \${$3+:} false; then :
1479
+  $as_echo_n "(cached) " >&6
1480
+fi
1481
+eval ac_res=\$$3
1482
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
1483
+$as_echo "$ac_res" >&6; }
1484
+else
1485
+  # Is the header compilable?
1486
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
1487
+$as_echo_n "checking $2 usability... " >&6; }
1488
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1489
+/* end confdefs.h.  */
1490
+$4
1491
+#include <$2>
1492
+_ACEOF
1493
+if ac_fn_c_try_compile "$LINENO"; then :
1494
+  ac_header_compiler=yes
1495
+else
1496
+  ac_header_compiler=no
1497
+fi
1498
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
1499
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
1500
+$as_echo "$ac_header_compiler" >&6; }
1501
+
1502
+# Is the header present?
1503
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
1504
+$as_echo_n "checking $2 presence... " >&6; }
1505
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1506
+/* end confdefs.h.  */
1507
+#include <$2>
1508
+_ACEOF
1509
+if ac_fn_c_try_cpp "$LINENO"; then :
1510
+  ac_header_preproc=yes
1511
+else
1512
+  ac_header_preproc=no
1513
+fi
1514
+rm -f conftest.err conftest.i conftest.$ac_ext
1515
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
1516
+$as_echo "$ac_header_preproc" >&6; }
1517
+
1518
+# So?  What about this header?
1519
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
1520
+  yes:no: )
1521
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
1522
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
1523
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
1524
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
1525
+    ;;
1526
+  no:yes:* )
1527
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
1528
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
1529
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
1530
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
1531
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
1532
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
1533
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
1534
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
1535
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
1536
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
1537
+( $as_echo "## --------------------------------- ##
1538
+## Report this to BUG-REPORT-ADDRESS ##
1539
+## --------------------------------- ##"
1540
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
1541
+    ;;
1542
+esac
1543
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
1544
+$as_echo_n "checking for $2... " >&6; }
1545
+if eval \${$3+:} false; then :
1546
+  $as_echo_n "(cached) " >&6
1547
+else
1548
+  eval "$3=\$ac_header_compiler"
1549
+fi
1550
+eval ac_res=\$$3
1551
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
1552
+$as_echo "$ac_res" >&6; }
1553
+fi
1554
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1555
+
1556
+} # ac_fn_c_check_header_mongrel
1557
+
1558
+# ac_fn_c_try_run LINENO
1559
+# ----------------------
1560
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
1561
+# that executables *can* be run.
1562
+ac_fn_c_try_run ()
1563
+{
1564
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1565
+  if { { ac_try="$ac_link"
1566
+case "(($ac_try" in
1567
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1568
+  *) ac_try_echo=$ac_try;;
1569
+esac
1570
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1571
+$as_echo "$ac_try_echo"; } >&5
1572
+  (eval "$ac_link") 2>&5
1573
+  ac_status=$?
1574
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1575
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
1576
+  { { case "(($ac_try" in
1577
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1578
+  *) ac_try_echo=$ac_try;;
1579
+esac
1580
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1581
+$as_echo "$ac_try_echo"; } >&5
1582
+  (eval "$ac_try") 2>&5
1583
+  ac_status=$?
1584
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1585
+  test $ac_status = 0; }; }; then :
1586
+  ac_retval=0
1587
+else
1588
+  $as_echo "$as_me: program exited with status $ac_status" >&5
1589
+       $as_echo "$as_me: failed program was:" >&5
1590
+sed 's/^/| /' conftest.$ac_ext >&5
1591
+
1592
+       ac_retval=$ac_status
1593
+fi
1594
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
1595
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1596
+  as_fn_set_status $ac_retval
1597
+
1598
+} # ac_fn_c_try_run
1599
+
1600
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
1601
+# -------------------------------------------------------
1602
+# Tests whether HEADER exists and can be compiled using the include files in
1603
+# INCLUDES, setting the cache variable VAR accordingly.
1604
+ac_fn_c_check_header_compile ()
1605
+{
1606
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1607
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
1608
+$as_echo_n "checking for $2... " >&6; }
1609
+if eval \${$3+:} false; then :
1610
+  $as_echo_n "(cached) " >&6
1611
+else
1612
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
1613
+/* end confdefs.h.  */
1614
+$4
1615
+#include <$2>
1616
+_ACEOF
1617
+if ac_fn_c_try_compile "$LINENO"; then :
1618
+  eval "$3=yes"
1619
+else
1620
+  eval "$3=no"
1621
+fi
1622
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
1623
+fi
1624
+eval ac_res=\$$3
1625
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
1626
+$as_echo "$ac_res" >&6; }
1627
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1628
+
1629
+} # ac_fn_c_check_header_compile
1630
+
1631
+# ac_fn_c_try_link LINENO
1632
+# -----------------------
1633
+# Try to link conftest.$ac_ext, and return whether this succeeded.
1634
+ac_fn_c_try_link ()
1635
+{
1636
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
1637
+  rm -f conftest.$ac_objext conftest$ac_exeext
1638
+  if { { ac_try="$ac_link"
1639
+case "(($ac_try" in
1640
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1641
+  *) ac_try_echo=$ac_try;;
1642
+esac
1643
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
1644
+$as_echo "$ac_try_echo"; } >&5
1645
+  (eval "$ac_link") 2>conftest.err
1646
+  ac_status=$?
1647
+  if test -s conftest.err; then
1648
+    grep -v '^ *+' conftest.err >conftest.er1
1649
+    cat conftest.er1 >&5
1650
+    mv -f conftest.er1 conftest.err
1651
+  fi
1652
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
1653
+  test $ac_status = 0; } && {
1654
+	 test -z "$ac_c_werror_flag" ||
1655
+	 test ! -s conftest.err
1656
+       } && test -s conftest$ac_exeext && {
1657
+	 test "$cross_compiling" = yes ||
1658
+	 test -x conftest$ac_exeext
1659
+       }; then :
1660
+  ac_retval=0
1661
+else
1662
+  $as_echo "$as_me: failed program was:" >&5
1663
+sed 's/^/| /' conftest.$ac_ext >&5
1664
+
1665
+	ac_retval=1
1666
+fi
1667
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
1668
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
1669
+  # interfere with the next link command; also delete a directory that is
1670
+  # left behind by Apple's compiler.  We do this before executing the actions.
1671
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
1672
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
1673
+  as_fn_set_status $ac_retval
1674
+
1675
+} # ac_fn_c_try_link
1387 1676
 cat >config.log <<_ACEOF
1388 1677
 This file contains any messages produced by compilers while
1389 1678
 running configure, to aid debugging if configure makes a mistake.
... ...
@@ -2552,6 +2841,514 @@ fi
2552 2841
 
2553 2842
 
2554 2843
 
2844
+ac_ext=c
2845
+ac_cpp='$CPP $CPPFLAGS'
2846
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
2847
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
2848
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
2849
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
2850
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
2851
+# On Suns, sometimes $CPP names a directory.
2852
+if test -n "$CPP" && test -d "$CPP"; then
2853
+  CPP=
2854
+fi
2855
+if test -z "$CPP"; then
2856
+  if ${ac_cv_prog_CPP+:} false; then :
2857
+  $as_echo_n "(cached) " >&6
2858
+else
2859
+      # Double quotes because CPP needs to be expanded
2860
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
2861
+    do
2862
+      ac_preproc_ok=false
2863
+for ac_c_preproc_warn_flag in '' yes
2864
+do
2865
+  # Use a header file that comes with gcc, so configuring glibc
2866
+  # with a fresh cross-compiler works.
2867
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
2868
+  # <limits.h> exists even on freestanding compilers.
2869
+  # On the NeXT, cc -E runs the code through the compiler's parser,
2870
+  # not just through cpp. "Syntax error" is here to catch this case.
2871
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2872
+/* end confdefs.h.  */
2873
+#ifdef __STDC__
2874
+# include <limits.h>
2875
+#else
2876
+# include <assert.h>
2877
+#endif
2878
+		     Syntax error
2879
+_ACEOF
2880
+if ac_fn_c_try_cpp "$LINENO"; then :
2881
+
2882
+else
2883
+  # Broken: fails on valid input.
2884
+continue
2885
+fi
2886
+rm -f conftest.err conftest.i conftest.$ac_ext
2887
+
2888
+  # OK, works on sane cases.  Now check whether nonexistent headers
2889
+  # can be detected and how.
2890
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2891
+/* end confdefs.h.  */
2892
+#include <ac_nonexistent.h>
2893
+_ACEOF
2894
+if ac_fn_c_try_cpp "$LINENO"; then :
2895
+  # Broken: success on invalid input.
2896
+continue
2897
+else
2898
+  # Passes both tests.
2899
+ac_preproc_ok=:
2900
+break
2901
+fi
2902
+rm -f conftest.err conftest.i conftest.$ac_ext
2903
+
2904
+done
2905
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
2906
+rm -f conftest.i conftest.err conftest.$ac_ext
2907
+if $ac_preproc_ok; then :
2908
+  break
2909
+fi
2910
+
2911
+    done
2912
+    ac_cv_prog_CPP=$CPP
2913
+
2914
+fi
2915
+  CPP=$ac_cv_prog_CPP
2916
+else
2917
+  ac_cv_prog_CPP=$CPP
2918
+fi
2919
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
2920
+$as_echo "$CPP" >&6; }
2921
+ac_preproc_ok=false
2922
+for ac_c_preproc_warn_flag in '' yes
2923
+do
2924
+  # Use a header file that comes with gcc, so configuring glibc
2925
+  # with a fresh cross-compiler works.
2926
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
2927
+  # <limits.h> exists even on freestanding compilers.
2928
+  # On the NeXT, cc -E runs the code through the compiler's parser,
2929
+  # not just through cpp. "Syntax error" is here to catch this case.
2930
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2931
+/* end confdefs.h.  */
2932
+#ifdef __STDC__
2933
+# include <limits.h>
2934
+#else
2935
+# include <assert.h>
2936
+#endif
2937
+		     Syntax error
2938
+_ACEOF
2939
+if ac_fn_c_try_cpp "$LINENO"; then :
2940
+
2941
+else
2942
+  # Broken: fails on valid input.
2943
+continue
2944
+fi
2945
+rm -f conftest.err conftest.i conftest.$ac_ext
2946
+
2947
+  # OK, works on sane cases.  Now check whether nonexistent headers
2948
+  # can be detected and how.
2949
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2950
+/* end confdefs.h.  */
2951
+#include <ac_nonexistent.h>
2952
+_ACEOF
2953
+if ac_fn_c_try_cpp "$LINENO"; then :
2954
+  # Broken: success on invalid input.
2955
+continue
2956
+else
2957
+  # Passes both tests.
2958
+ac_preproc_ok=:
2959
+break
2960
+fi
2961
+rm -f conftest.err conftest.i conftest.$ac_ext
2962
+
2963
+done
2964
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
2965
+rm -f conftest.i conftest.err conftest.$ac_ext
2966
+if $ac_preproc_ok; then :
2967
+
2968
+else
2969
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
2970
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
2971
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
2972
+See \`config.log' for more details" "$LINENO" 5; }
2973
+fi
2974
+
2975
+ac_ext=c
2976
+ac_cpp='$CPP $CPPFLAGS'
2977
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
2978
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
2979
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
2980
+
2981
+
2982
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
2983
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
2984
+if ${ac_cv_path_GREP+:} false; then :
2985
+  $as_echo_n "(cached) " >&6
2986
+else
2987
+  if test -z "$GREP"; then
2988
+  ac_path_GREP_found=false
2989
+  # Loop through the user's path and test for each of PROGNAME-LIST
2990
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2991
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
2992
+do
2993
+  IFS=$as_save_IFS
2994
+  test -z "$as_dir" && as_dir=.
2995
+    for ac_prog in grep ggrep; do
2996
+    for ac_exec_ext in '' $ac_executable_extensions; do
2997
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
2998
+      as_fn_executable_p "$ac_path_GREP" || continue
2999
+# Check for GNU ac_path_GREP and select it if it is found.
3000
+  # Check for GNU $ac_path_GREP
3001
+case `"$ac_path_GREP" --version 2>&1` in
3002
+*GNU*)
3003
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
3004
+*)
3005
+  ac_count=0
3006
+  $as_echo_n 0123456789 >"conftest.in"
3007
+  while :
3008
+  do
3009
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
3010
+    mv "conftest.tmp" "conftest.in"
3011
+    cp "conftest.in" "conftest.nl"
3012
+    $as_echo 'GREP' >> "conftest.nl"
3013
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
3014
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
3015
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
3016
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
3017
+      # Best one so far, save it but keep looking for a better one
3018
+      ac_cv_path_GREP="$ac_path_GREP"
3019
+      ac_path_GREP_max=$ac_count
3020
+    fi
3021
+    # 10*(2^10) chars as input seems more than enough
3022
+    test $ac_count -gt 10 && break
3023
+  done
3024
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
3025
+esac
3026
+
3027
+      $ac_path_GREP_found && break 3
3028
+    done
3029
+  done
3030
+  done
3031
+IFS=$as_save_IFS
3032
+  if test -z "$ac_cv_path_GREP"; then
3033
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
3034
+  fi
3035
+else
3036
+  ac_cv_path_GREP=$GREP
3037
+fi
3038
+
3039
+fi
3040
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
3041
+$as_echo "$ac_cv_path_GREP" >&6; }
3042
+ GREP="$ac_cv_path_GREP"
3043
+
3044
+
3045
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
3046
+$as_echo_n "checking for egrep... " >&6; }
3047
+if ${ac_cv_path_EGREP+:} false; then :
3048
+  $as_echo_n "(cached) " >&6
3049
+else
3050
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
3051
+   then ac_cv_path_EGREP="$GREP -E"
3052
+   else
3053
+     if test -z "$EGREP"; then
3054
+  ac_path_EGREP_found=false
3055
+  # Loop through the user's path and test for each of PROGNAME-LIST
3056
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
3057
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
3058
+do
3059
+  IFS=$as_save_IFS
3060
+  test -z "$as_dir" && as_dir=.
3061
+    for ac_prog in egrep; do
3062
+    for ac_exec_ext in '' $ac_executable_extensions; do
3063
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
3064
+      as_fn_executable_p "$ac_path_EGREP" || continue
3065
+# Check for GNU ac_path_EGREP and select it if it is found.
3066
+  # Check for GNU $ac_path_EGREP
3067
+case `"$ac_path_EGREP" --version 2>&1` in
3068
+*GNU*)
3069
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
3070
+*)
3071
+  ac_count=0
3072
+  $as_echo_n 0123456789 >"conftest.in"
3073
+  while :
3074
+  do
3075
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
3076
+    mv "conftest.tmp" "conftest.in"
3077
+    cp "conftest.in" "conftest.nl"
3078
+    $as_echo 'EGREP' >> "conftest.nl"
3079
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
3080
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
3081
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
3082
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
3083
+      # Best one so far, save it but keep looking for a better one
3084
+      ac_cv_path_EGREP="$ac_path_EGREP"
3085
+      ac_path_EGREP_max=$ac_count
3086
+    fi
3087
+    # 10*(2^10) chars as input seems more than enough
3088
+    test $ac_count -gt 10 && break
3089
+  done
3090
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
3091
+esac
3092
+
3093
+      $ac_path_EGREP_found && break 3
3094
+    done
3095
+  done
3096
+  done
3097
+IFS=$as_save_IFS
3098
+  if test -z "$ac_cv_path_EGREP"; then
3099
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
3100
+  fi
3101
+else
3102
+  ac_cv_path_EGREP=$EGREP
3103
+fi
3104
+
3105
+   fi
3106
+fi
3107
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
3108
+$as_echo "$ac_cv_path_EGREP" >&6; }
3109
+ EGREP="$ac_cv_path_EGREP"
3110
+
3111
+
3112
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
3113
+$as_echo_n "checking for ANSI C header files... " >&6; }
3114
+if ${ac_cv_header_stdc+:} false; then :
3115
+  $as_echo_n "(cached) " >&6
3116
+else
3117
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3118
+/* end confdefs.h.  */
3119
+#include <stdlib.h>
3120
+#include <stdarg.h>
3121
+#include <string.h>
3122
+#include <float.h>
3123
+
3124
+int
3125
+main ()
3126
+{
3127
+
3128
+  ;
3129
+  return 0;
3130
+}
3131
+_ACEOF
3132
+if ac_fn_c_try_compile "$LINENO"; then :
3133
+  ac_cv_header_stdc=yes
3134
+else
3135
+  ac_cv_header_stdc=no
3136
+fi
3137
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
3138
+
3139
+if test $ac_cv_header_stdc = yes; then
3140
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
3141
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3142
+/* end confdefs.h.  */
3143
+#include <string.h>
3144
+
3145
+_ACEOF
3146
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
3147
+  $EGREP "memchr" >/dev/null 2>&1; then :
3148
+
3149
+else
3150
+  ac_cv_header_stdc=no
3151
+fi
3152
+rm -f conftest*
3153
+
3154
+fi
3155
+
3156
+if test $ac_cv_header_stdc = yes; then
3157
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
3158
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3159
+/* end confdefs.h.  */
3160
+#include <stdlib.h>
3161
+
3162
+_ACEOF
3163
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
3164
+  $EGREP "free" >/dev/null 2>&1; then :
3165
+
3166
+else
3167
+  ac_cv_header_stdc=no
3168
+fi
3169
+rm -f conftest*
3170
+
3171
+fi
3172
+
3173
+if test $ac_cv_header_stdc = yes; then
3174
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
3175
+  if test "$cross_compiling" = yes; then :
3176
+  :
3177
+else
3178
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3179
+/* end confdefs.h.  */
3180
+#include <ctype.h>
3181
+#include <stdlib.h>
3182
+#if ((' ' & 0x0FF) == 0x020)
3183
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
3184
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
3185
+#else
3186
+# define ISLOWER(c) \
3187
+		   (('a' <= (c) && (c) <= 'i') \
3188
+		     || ('j' <= (c) && (c) <= 'r') \
3189
+		     || ('s' <= (c) && (c) <= 'z'))
3190
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
3191
+#endif
3192
+
3193
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
3194
+int
3195
+main ()
3196
+{
3197
+  int i;
3198
+  for (i = 0; i < 256; i++)
3199
+    if (XOR (islower (i), ISLOWER (i))
3200
+	|| toupper (i) != TOUPPER (i))
3201
+      return 2;
3202
+  return 0;
3203
+}
3204
+_ACEOF
3205
+if ac_fn_c_try_run "$LINENO"; then :
3206
+
3207
+else
3208
+  ac_cv_header_stdc=no
3209
+fi
3210
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
3211
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
3212
+fi
3213
+
3214
+fi
3215
+fi
3216
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
3217
+$as_echo "$ac_cv_header_stdc" >&6; }
3218
+if test $ac_cv_header_stdc = yes; then
3219
+
3220
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
3221
+
3222
+fi
3223
+
3224
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
3225
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
3226
+		  inttypes.h stdint.h unistd.h
3227
+do :
3228
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
3229
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
3230
+"
3231
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
3232
+  cat >>confdefs.h <<_ACEOF
3233
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
3234
+_ACEOF
3235
+
3236
+fi
3237
+
3238
+done
3239
+
3240
+
3241
+for ac_header in openssl/hmac.h openssl/evp.h
3242
+do :
3243
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
3244
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
3245
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
3246
+  cat >>confdefs.h <<_ACEOF
3247
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
3248
+_ACEOF
3249
+
3250
+else
3251
+  as_fn_error $? "\"Can't find Openssl\"" "$LINENO" 5
3252
+fi
3253
+
3254
+done
3255
+
3256
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_library_init in -lssl" >&5
3257
+$as_echo_n "checking for SSL_library_init in -lssl... " >&6; }
3258
+if ${ac_cv_lib_ssl_SSL_library_init+:} false; then :
3259
+  $as_echo_n "(cached) " >&6
3260
+else
3261
+  ac_check_lib_save_LIBS=$LIBS
3262
+LIBS="-lssl  $LIBS"
3263
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3264
+/* end confdefs.h.  */
3265
+
3266
+/* Override any GCC internal prototype to avoid an error.
3267
+   Use char because int might match the return type of a GCC
3268
+   builtin and then its argument prototype would still apply.  */
3269
+#ifdef __cplusplus
3270
+extern "C"
3271
+#endif
3272
+char SSL_library_init ();
3273
+int
3274
+main ()
3275
+{
3276
+return SSL_library_init ();
3277
+  ;
3278
+  return 0;
3279
+}
3280
+_ACEOF
3281
+if ac_fn_c_try_link "$LINENO"; then :
3282
+  ac_cv_lib_ssl_SSL_library_init=yes
3283
+else
3284
+  ac_cv_lib_ssl_SSL_library_init=no
3285
+fi
3286
+rm -f core conftest.err conftest.$ac_objext \
3287
+    conftest$ac_exeext conftest.$ac_ext
3288
+LIBS=$ac_check_lib_save_LIBS
3289
+fi
3290
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_library_init" >&5
3291
+$as_echo "$ac_cv_lib_ssl_SSL_library_init" >&6; }
3292
+if test "x$ac_cv_lib_ssl_SSL_library_init" = xyes; then :
3293
+  cat >>confdefs.h <<_ACEOF
3294
+#define HAVE_LIBSSL 1
3295
+_ACEOF
3296
+
3297
+  LIBS="-lssl $LIBS"
3298
+
3299
+else
3300
+  as_fn_error $? "\"Can't find -lssl\"" "$LINENO" 5
3301
+fi
3302
+
3303
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_EncryptInit in -lcrypto" >&5
3304
+$as_echo_n "checking for EVP_EncryptInit in -lcrypto... " >&6; }
3305
+if ${ac_cv_lib_crypto_EVP_EncryptInit+:} false; then :
3306
+  $as_echo_n "(cached) " >&6
3307
+else
3308
+  ac_check_lib_save_LIBS=$LIBS
3309
+LIBS="-lcrypto  $LIBS"
3310
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3311
+/* end confdefs.h.  */
3312
+
3313
+/* Override any GCC internal prototype to avoid an error.
3314
+   Use char because int might match the return type of a GCC
3315
+   builtin and then its argument prototype would still apply.  */
3316
+#ifdef __cplusplus
3317
+extern "C"
3318
+#endif
3319
+char EVP_EncryptInit ();
3320
+int
3321
+main ()
3322
+{
3323
+return EVP_EncryptInit ();
3324
+  ;
3325
+  return 0;
3326
+}
3327
+_ACEOF
3328
+if ac_fn_c_try_link "$LINENO"; then :
3329
+  ac_cv_lib_crypto_EVP_EncryptInit=yes
3330
+else
3331
+  ac_cv_lib_crypto_EVP_EncryptInit=no
3332
+fi
3333
+rm -f core conftest.err conftest.$ac_objext \
3334
+    conftest$ac_exeext conftest.$ac_ext
3335
+LIBS=$ac_check_lib_save_LIBS
3336
+fi
3337
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_EncryptInit" >&5
3338
+$as_echo "$ac_cv_lib_crypto_EVP_EncryptInit" >&6; }
3339
+if test "x$ac_cv_lib_crypto_EVP_EncryptInit" = xyes; then :
3340
+  cat >>confdefs.h <<_ACEOF
3341
+#define HAVE_LIBCRYPTO 1
3342
+_ACEOF
3343
+
3344
+  LIBS="-lcrypto $LIBS"
3345
+
3346
+else
3347
+  as_fn_error $? "\"Can't find -lcrypto\"" "$LINENO" 5
3348
+fi
3349
+
3350
+
3351
+
2555 3352
 ac_config_files="$ac_config_files Makefile"
2556 3353
 
2557 3354
 cat >confcache <<\_ACEOF
... ...
@@ -3827,6 +4624,8 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
3827 4624
 fi
3828 4625
 
3829 4626
 
4627
+
4628
+
3830 4629
 if test "$PAM_MODULE_DIRECTORY" = "$DEFAULT_PAM_MODULE_DIRECTORY"; then
3831 4630
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
3832 4631
         **
... ...
@@ -3854,5 +4653,3 @@ else
3854 4653
     { $as_echo "$as_me:${as_lineno-$LINENO}: PAM module installation directory: $PAM_MODULE_DIRECTORY" >&5
3855 4654
 $as_echo "$as_me: PAM module installation directory: $PAM_MODULE_DIRECTORY" >&6;}
3856 4655
 fi
3857
-
3858
-
... ...
@@ -26,10 +26,16 @@ AC_ARG_WITH(pam-module-directory,
26 26
     PAM_MODULE_DIRECTORY="$DEFAULT_PAM_MODULE_DIRECTORY")
27 27
 AC_SUBST(PAM_MODULE_DIRECTORY)
28 28
 
29
+AC_CHECK_HEADERS([openssl/hmac.h openssl/evp.h],,[AC_MSG_ERROR("Can't find Openssl")])
30
+AC_CHECK_LIB([ssl], [SSL_library_init],,[AC_MSG_ERROR("Can't find -lssl")])
31
+AC_CHECK_LIB([crypto], [EVP_EncryptInit],,[AC_MSG_ERROR("Can't find -lcrypto")])
32
+
29 33
 
30 34
 AC_CONFIG_FILES([Makefile])
31 35
 AC_OUTPUT
32 36
 
37
+
38
+
33 39
 if test "$PAM_MODULE_DIRECTORY" = "$DEFAULT_PAM_MODULE_DIRECTORY"; then
34 40
     AC_MSG_WARN([
35 41
         **
... ...
@@ -45,5 +51,3 @@ if test "$PAM_MODULE_DIRECTORY" = "$DEFAULT_PAM_MODULE_DIRECTORY"; then
45 51
 else
46 52
     AC_MSG_NOTICE([PAM module installation directory: $PAM_MODULE_DIRECTORY])
47 53
 fi
48
-
49
-
... ...
@@ -16,20 +16,22 @@
16 16
 
17 17
 #include "conversation.h"
18 18
 
19
-
20 19
 namespace
21 20
 {
22 21
 class impl : public conversation_ifc
23 22
 {
24 23
 private:
25 24
     pam pam_;
26
-    pam_conv_result conversation(const std::string &msg, int msg_style, const pam_request &request) {
25
+    pam_conv_result conversation (const std::string &msg, int msg_style,
26
+                                  const pam_request &request)
27
+    {
27 28
         const pam_conv *conv;
28 29
         int get_conv_result = pam_.get_conv (request.handle(), &conv);
30
+
29 31
         if (get_conv_result != PAM_SUCCESS) {
30 32
             return pam_conv_result {get_conv_result, PAM_CONV_ERR, std::vector<pam_response *>()};
31 33
         }
32
-        
34
+
33 35
         pam_message message;
34 36
         message.msg = const_cast<char *> (msg.c_str());
35 37
         message.msg_style = msg_style;
... ...
@@ -39,8 +41,8 @@ private:
39 41
         std::vector<pam_response *> responses (1);
40 42
 
41 43
         int conv_result = conv->conv (1, messages.data(),
42
-                                             responses.data(),
43
-                                             conv->appdata_ptr);
44
+                                      responses.data(),
45
+                                      conv->appdata_ptr);
44 46
 
45 47
         return pam_conv_result {get_conv_result, conv_result, responses};
46 48
     }
... ...
@@ -51,12 +53,16 @@ public:
51 53
     {
52 54
         conversation_result result;
53 55
 
54
-        pam_conv_result token_result (conversation("Dual control token: ", PAM_PROMPT_ECHO_OFF, request));
56
+        pam_conv_result token_result (conversation ("Dual control token: ",
57
+                                      PAM_PROMPT_ECHO_OFF, request));
58
+
55 59
         if (token_result.get_conv_result != PAM_SUCCESS) {
56 60
             return result;
57 61
         }
58 62
 
59
-        pam_conv_result reason_result (conversation("Reason: ", PAM_PROMPT_ECHO_ON, request));
63
+        pam_conv_result reason_result (conversation ("Reason: ", PAM_PROMPT_ECHO_ON,
64
+                                       request));
65
+
60 66
         if (reason_result.get_conv_result != PAM_SUCCESS) {
61 67
             return result;
62 68
         }
... ...
@@ -18,6 +18,7 @@
18 18
 #include "user.h"
19 19
 #include "sys_unistd.h"
20 20
 #include "sys_pwd.h"
21
+#include "sys_time.h"
21 22
 #include "token.h"
22 23
 #include "system.h"
23 24
 #include "sys_fstream.h"
... ...
@@ -39,9 +40,12 @@ installer init_installer()
39 40
     unistd unistd (unistd::create());
40 41
     directory directory (directory::create (unistd, pwd));
41 42
     stdlib stdlib (stdlib::get());
42
-    generator generator{make_generator (stdlib)};
43
-    installer installer (installer::create (tokens, unistd,
44
-                                            directory, generator));
43
+    sys_time time (sys_time::get());
44
+    int code_digits = 6;
45
+    auto the_generator = std::make_shared<totp_generator> (time, "\x00",
46
+                         code_digits);
47
+    installer installer (installer::create (tokens, unistd, directory,
48
+                                            the_generator));
45 49
 
46 50
     return installer;
47 51
 }
48 52
new file mode 100644
... ...
@@ -0,0 +1,125 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
12
+#include "generator.h"
13
+#include <iostream>
14
+
15
+#include <openssl/hmac.h>
16
+#include <openssl/evp.h>
17
+
18
+namespace
19
+{
20
+int ipow (int base, int exp)
21
+{
22
+    int result = 1;
23
+
24
+    while (exp) {
25
+        if (exp & 1) {
26
+            result *= base;
27
+        }
28
+
29
+        exp >>= 1;
30
+        base *= base;
31
+    }
32
+
33
+    return result;
34
+}
35
+
36
+unsigned char *timeToBytes (unsigned long long time, unsigned char *data,
37
+                            size_t data_size)
38
+{
39
+    for (int idx = data_size - 1; idx > -1; idx--) {
40
+        unsigned char next_digit = time & 0xff;
41
+        data[idx] = next_digit;
42
+        time >>= 8;
43
+    }
44
+
45
+    return data;
46
+}
47
+
48
+unsigned long bytesToInt (const std::string &bytes)
49
+{
50
+    unsigned long result = 0;
51
+    auto          byteCount = bytes.size() - 1;
52
+
53
+    for (auto byte = bytes.cbegin(); byte < bytes.cend(); byte++, byteCount--) {
54
+        const uint8_t val = static_cast<uint8_t> (*byte);
55
+        result |= val << (byteCount * 8);
56
+    }
57
+
58
+    return result;
59
+}
60
+
61
+class token_generator_impl : public token_generator_ifc
62
+{
63
+private:
64
+    const sys_time &clock;
65
+    unsigned int code_digits;
66
+    const std::string key;
67
+
68
+private:
69
+    unsigned long truncate (const std::string &mac) const
70
+    {
71
+        uint8_t offset = static_cast<uint8_t > (mac[19]) & static_cast<uint8_t>
72
+                         (0x0f);
73
+        std::string  offsetBytes = mac.substr (offset, 4);
74
+        return bytesToInt (offsetBytes) & 0x7fffffff;
75
+    }
76
+
77
+    std::string zero_fill (unsigned long result, int digits) const
78
+    {
79
+        std::ostringstream result_stream;
80
+        result_stream << std::setw (digits) << std::setfill ('0') << result;
81
+        return result_stream.str();
82
+    }
83
+
84
+    std::string hotp (const std::string &key, const unsigned char *data,
85
+                      size_t data_size, const int digits=6) const
86
+    {
87
+        unsigned char *digest = HMAC (EVP_sha1(), key.c_str(), key.size(), data,
88
+                                      data_size, NULL, NULL);
89
+        std::string digest_s = std::string (reinterpret_cast<const char *> (digest),
90
+                                            20);
91
+        unsigned long result = truncate (digest_s) % ipow (10,digits);
92
+
93
+        return zero_fill (result, digits);
94
+    }
95
+
96
+public:
97
+    token_generator_impl (const sys_time &clock,
98
+                          const std::string &key,
99
+                          const int code_digits) :
100
+        clock (clock), code_digits (code_digits),
101
+        key (key)
102
+    {}
103
+
104
+    std::string generate_token () const override
105
+    {
106
+        // Assuming time is > 0, integer division produces the result we want.
107
+        const time_t &time_chunk = clock.time (nullptr) / 30;
108
+
109
+        unsigned char data[8] = {0,0,0,0,0,0,0,0};
110
+        timeToBytes (time_chunk, data, 8);
111
+
112
+        return hotp (key, data, 8, code_digits);
113
+    }
114
+};
115
+}
116
+
117
+// Generator goes here....
118
+
119
+totp_generator::totp_generator (
120
+    const sys_time &clock,
121
+    const std::string &key_c,
122
+    const int code_digits) :
123
+    delegate_ (std::make_shared<token_generator_impl> (clock, key_c,
124
+               code_digits))
125
+{}
... ...
@@ -17,25 +17,41 @@
17 17
 #include <sstream>
18 18
 #include <iomanip>
19 19
 #include <cmath>
20
+#include <ctime>
20 21
 
21 22
 #include "sys_stdlib.h"
23
+#include "sys_time.h"
22 24
 
23
-using generator = std::function<std::string()>;
25
+int ipow (int base, int exp);
26
+time_t time_step (const time_t time, const int step);
24 27
 
25
-inline    std::string token_from_int (int x)
28
+class token_generator_ifc
26 29
 {
27
-    int v = std::abs (x % 1000000);
28
-    std::ostringstream is;
29
-    is << std::setfill ('0') << std::setw (6)<< v;
30
-    return is.str();
31
-}
30
+public:
31
+    virtual std::string generate_token () const = 0;
32 32
 
33
-inline generator make_generator (const stdlib &stdlib)
33
+};
34
+
35
+class totp_generator
34 36
 {
35
-    return [stdlib] {
36
-        return token_from_int (stdlib.rand());
37
+public:
38
+    using delegate = std::shared_ptr<token_generator_ifc>;
39
+
40
+private:
41
+    delegate delegate_;
42
+
43
+public:
44
+    std::string generate_token () const
45
+    {
46
+        return delegate_->generate_token();
37 47
     };
38
-}
39 48
 
40
-#endif
49
+    totp_generator (delegate delegate_) :
50
+        delegate_ (delegate_)
51
+    {}
52
+    totp_generator (const sys_time &clock,
53
+                    const std::string &key_c,
54
+                    const int code_digits);
55
+};
41 56
 
57
+#endif
... ...
@@ -13,9 +13,12 @@
13 13
 #include <initializer_list>
14 14
 #include <vector>
15 15
 #include <climits>
16
+#include <ctime>
17
+#include <iostream>
16 18
 
17 19
 #include "generator.h"
18 20
 #include "sys_stdlib.h"
21
+#include "sys_time.h"
19 22
 #include "test_util.h"
20 23
 
21 24
 class fake_stdlib : public stdlib_ifc
... ...
@@ -40,16 +43,46 @@ public:
40 43
     }
41 44
 };
42 45
 
46
+class fake_time : public sys_time_ifc
47
+{
48
+
49
+private:
50
+    std::vector<time_t> samples_;
51
+    mutable std::vector<time_t>::iterator current_;
52
+public:
53
+    fake_time ( const std::initializer_list<time_t> &samples)
54
+        : samples_ (samples.begin(), samples.end()),
55
+          current_ (samples_.begin()) {}
56
+    time_t time (time_t *time_ptr) const override
57
+    {
58
+        if (current_ != samples_.end()) {
59
+            auto rval = *current_;
60
+
61
+            if (time_ptr != nullptr) {
62
+                *time_ptr = rval;
63
+            }
64
+
65
+            current_ += 1;
66
+            return rval;
67
+        }
68
+
69
+        return 0;
70
+    }
71
+};
72
+
43 73
 int six_digits()
44 74
 {
45 75
     // given
46
-    std::initializer_list<int> samples { 1 };
47
-    auto test_stdlib = std::make_shared<fake_stdlib> (samples);
48
-    stdlib stdlib (test_stdlib);
49
-    generator generator = make_generator (stdlib);
76
+    std::initializer_list<time_t> samples { 1 };
77
+    auto test_stdtime = std::make_shared<fake_time> (samples);
78
+
79
+    sys_time stdtime (test_stdtime);
80
+    // Fake the Key
81
+    std::string key = "\xff\x91\xebO\x04\xa4\xda$\xd2$a\x95Vs\xaf`";
82
+    auto generator = totp_generator (stdtime, key, 6);
50 83
 
51 84
     // when
52
-    auto actual = generator();
85
+    auto actual = generator.generate_token();
53 86
 
54 87
     // then
55 88
     check (actual.size() == 6, "size is wrong");
... ...
@@ -62,30 +95,36 @@ int six_digits()
62 95
 int modulated_source_modulates_tokens()
63 96
 {
64 97
     // given
65
-    std::initializer_list<int> samples { 1, 2, 3 };
66
-    auto test_stdlib = std::make_shared<fake_stdlib> (samples);
67
-    stdlib stdlib (test_stdlib);
68
-    generator generator = make_generator (stdlib);
98
+    std::initializer_list<time_t> samples { 1, 31 };
99
+    auto test_stdtime = std::make_shared<fake_time> (samples);
100
+
101
+    sys_time stdtime (test_stdtime);
102
+    // Fake the Key
103
+    std::string key = "\xff\x91\xebO\x04\xa4\xda$\xd2$a\x95Vs\xaf`";
104
+    auto generator = totp_generator (stdtime, key, 6);
69 105
 
70 106
     // when
71
-    auto actual1 = generator();
72
-    auto actual2 = generator();
107
+    auto actual1 = generator.generate_token();
108
+    auto actual2 = generator.generate_token();
73 109
 
74 110
     // then
75
-    check (actual1 != actual2, "samples should be different");
111
+    check (actual1 != actual2, "tokens should be different");
76 112
     succeed();
77 113
 }
78 114
 
79 115
 int int_max()
80 116
 {
81 117
     // given
82
-    std::initializer_list<int> samples { INT_MAX };
83
-    auto test_stdlib = std::make_shared<fake_stdlib> (samples);
84
-    stdlib stdlib (test_stdlib);
85
-    generator generator = make_generator (stdlib);
118
+    std::initializer_list<time_t> samples { INT_MAX };
119
+    auto test_stdtime = std::make_shared<fake_time> (samples);
120
+
121
+    sys_time stdtime (test_stdtime);
122
+    // Fake the Key
123
+    std::string key = "\xff\x91\xebO\x04\xa4\xda$\xd2$a\x95Vs\xaf`";
124
+    auto generator = totp_generator (stdtime, key, 6);
86 125
 
87 126
     // when
88
-    auto actual = generator();
127
+    auto actual = generator.generate_token();
89 128
 
90 129
     // then
91 130
     check (actual.size() == 6, "size is wrong");
... ...
@@ -98,13 +137,16 @@ int int_max()
98 137
 int int_min()
99 138
 {
100 139
     // given
101
-    std::initializer_list<int> samples { INT_MIN };
102
-    auto test_stdlib = std::make_shared<fake_stdlib> (samples);
103
-    stdlib stdlib (test_stdlib);
104
-    generator generator = make_generator (stdlib);
140
+    std::initializer_list<time_t> samples { INT_MIN };
141
+    auto test_stdtime = std::make_shared<fake_time> (samples);
142
+
143
+    sys_time stdtime (test_stdtime);
144
+    // Fake the Key
145
+    std::string key = "\xff\x91\xebO\x04\xa4\xda$\xd2$a\x95Vs\xaf`";
146
+    auto generator = totp_generator (stdtime, key, 6);
105 147
 
106 148
     // when
107
-    auto actual = generator();
149
+    auto actual = generator.generate_token();
108 150
 
109 151
     // then
110 152
     check (actual.size() == 6, "size is wrong");
... ...
@@ -114,12 +156,39 @@ int int_min()
114 156
     succeed();
115 157
 }
116 158
 
159
+// totp test
160
+int int_precomputed()
161
+{
162
+    // given
163
+    // The token for key 76I6WTYEUTNCJUREMGKVM45PMA and time '2017/01/01 00:00:00' is 258675
164
+    time_t theTime = 1483257600;
165
+    /// TODO: int -> time_t
166
+    std::initializer_list<time_t> samples { theTime }; //
167
+    auto test_stdtime = std::make_shared<fake_time> (samples);
168
+
169
+    sys_time stdtime (test_stdtime);
170
+    // Fake the Key
171
+    std::string key = "\xff\x91\xebO\x04\xa4\xda$\xd2$a\x95Vs\xaf`";
172
+    auto generator = totp_generator (stdtime, key, 6);
173
+    std::string expected = "258675";
174
+
175
+    // when
176
+    auto actual = generator.generate_token();
177
+
178
+    // then
179
+    check (actual.size() == 6, "size is wrong");
180
+    check (actual == expected,
181
+           "precomputed value failed to match"); // TODO: Does == work for std::string like I want it to?
182
+    succeed();
183
+}
184
+
117 185
 int run_tests()
118 186
 {
119 187
     test (six_digits);
120 188
     test (modulated_source_modulates_tokens);
121 189
     test (int_max);
122 190
     test (int_min);
191
+    test (int_precomputed);
123 192
     succeed();
124 193
 }
125 194
 
... ...
@@ -27,10 +27,11 @@ private:
27 27
     tokens tokens_;
28 28
     unistd unistd_;
29 29
     directory directory_;
30
-    generator generator_;
30
+    std::shared_ptr<totp_generator> generator_;
31 31
 public:
32 32
     impl (const tokens &tokens, const unistd &unistd,
33
-          const directory &directory, const generator &generator) :
33
+          const directory &directory,
34
+          const std::shared_ptr<totp_generator> generator) :
34 35
         tokens_ (tokens), unistd_ (unistd), directory_ (directory),
35 36
         generator_ (generator) {}
36 37
     std::string install_token() const override
... ...
@@ -50,7 +51,7 @@ public:
50 51
         }
51 52
 
52 53
         user user (found_user[0]);
53
-        std::string token (generator_());
54
+        std::string token (generator_->generate_token());
54 55
         tokens_.save (user, token);
55 56
         return token;
56 57
     }
... ...
@@ -59,7 +60,7 @@ public:
59 60
 }
60 61
 
61 62
 installer installer::create (const tokens &tokens, const unistd &unistd,
62
-                             const directory &directory, const generator &generator)
63
+                             const directory &directory, const std::shared_ptr<totp_generator> generator)
63 64
 {
64 65
     return installer (std::make_shared<impl> (tokens, unistd, directory,
65 66
                       generator));
... ...
@@ -44,7 +44,8 @@ public:
44 44
         return delegate_->install_token();
45 45
     }
46 46
     static installer create (const tokens &tokens, const unistd &unistd,
47
-                             const directory &directory, const generator &generator);
47
+                             const directory &directory,
48
+                             const std::shared_ptr<totp_generator> generator);
48 49
 };
49 50
 
50 51
 #endif
... ...
@@ -18,6 +18,7 @@
18 18
 #include "user.h"
19 19
 #include "token.h"
20 20
 #include "test_util.h"
21
+#include "generator.h"
21 22
 
22 23
 class mock_tokens : public tokens_ifc
23 24
 {
... ...
@@ -50,6 +51,21 @@ public:
50 51
     }
51 52
 };
52 53
 
54
+class fake_totp_generator : public token_generator_ifc
55
+{
56
+private:
57
+    std::string expected_token;
58
+public:
59
+    fake_totp_generator (const std::string expected_token = "000000"):
60
+        expected_token (expected_token)
61
+    {}
62
+
63
+    std::string generate_token() const override
64
+    {
65
+        return expected_token;
66
+    }
67
+};
68
+
53 69
 class fake_directory : public directory_ifc
54 70
 {
55 71
 private:
... ...
@@ -81,7 +97,9 @@ int installs_token()
81 97
     tokens tokens{test_tokens};
82 98
     unistd unistd (std::make_shared<fake_unistd> (user_name));
83 99
     directory directory (std::make_shared<fake_directory> (user_name));
84
-    generator generator = [&] { return token; };
100
+    std::shared_ptr<fake_totp_generator> fake_generator =
101
+        std::make_shared<fake_totp_generator> (token);
102
+    auto generator = std::make_shared<totp_generator> (fake_generator);
85 103
 
86 104
     installer installer = installer::create (tokens, unistd, directory,
87 105
                           generator);
... ...
@@ -104,7 +122,8 @@ int unistd_does_not_find_user_name_nullptr_case()
104 122
     tokens tokens{test_tokens};
105 123
     unistd unistd (std::make_shared<fail_unistd>());
106 124
     directory directory (std::make_shared<fake_directory> (user_name));
107
-    generator generator = [&] { return token; };
125
+    auto generator = std::make_shared<totp_generator>
126
+                     (std::make_shared<fake_totp_generator>());
108 127
 
109 128
     installer installer = installer::create (tokens, unistd, directory,
110 129
                           generator);
... ...
@@ -128,7 +147,8 @@ int unistd_does_not_find_user_name_empty_string_case()
128 147
     tokens tokens{test_tokens};
129 148
     unistd unistd (std::make_shared<fake_unistd> (""));
130 149
     directory directory (std::make_shared<fake_directory> (user_name));
131
-    generator generator = [&] { return token; };
150
+    auto generator = std::shared_ptr<totp_generator> (new totp_generator (
151
+                         std::make_shared<fake_totp_generator>()));
132 152
 
133 153
     installer installer = installer::create (tokens, unistd, directory,
134 154
                           generator);
... ...
@@ -151,7 +171,8 @@ int directory_finds_no_user_info()
151 171
     tokens tokens{test_tokens};
152 172
     unistd unistd (std::make_shared<fake_unistd> (user_name));
153 173
     directory directory (std::make_shared<fake_directory> ("not the user"));
154
-    generator generator = [&] { return token; };
174
+    auto generator = std::shared_ptr<totp_generator> (new totp_generator (
175
+                         std::make_shared<fake_totp_generator>()));
155 176
 
156 177
     installer installer = installer::create (tokens, unistd, directory,
157 178
                           generator);
... ...
@@ -16,7 +16,7 @@
16 16
 #include <cstdio>
17 17
 #define check(assertion, msg) \
18 18
     if (!(assertion)) { \
19
-      fprintf(stderr, "assertion failed: %s\n", msg); \
19
+      fprintf(stderr, "> assertion failed: %s\n", msg); \
20 20
       return 0; \
21 21
     }
22 22
 
... ...
@@ -32,11 +32,13 @@
32 32
 
33 33
 #define test(NAME) \
34 34
     { \
35
-      int result = NAME (); \
36
-      if (!result) { \
37
-          fprintf(stderr, "test failed: %s\n", #NAME); \
38
-          return 0; \
39
-      } \
35
+        int result = NAME (); \
36
+        if (!result) { \
37
+            fprintf(stderr, "! <%s:%d> test failed: %s\n", __FILE__, __LINE__, #NAME); \
38
+	    return 0; \
39
+        } else { \
40
+            fprintf (stderr, "> test passed: %s\n", #NAME); \
41
+        } \
40 42
     }
41 43
 
42 44
 #define succeed() return 1