authenticator.pp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. { Demo Google-authenticator compatible authenticator app
  2. Copyright (C) 2022 Michael Van Canneyt [email protected]
  3. This source is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
  4. published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
  5. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  6. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  7. A copy of the GNU General Public License is available on the World Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can
  8. also obtain it by writing to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
  9. }
  10. {$mode objfpc}
  11. {$h+}
  12. uses sysutils, classes, onetimepass, inifiles, custapp;
  13. Type
  14. TMode = (mError,mHelp,mAdd,mDelete,mPrint,mGenerate,mList,mCheck);
  15. { TAuthenticatorApplication }
  16. TAuthenticatorApplication = Class(TCustomApplication)
  17. Private
  18. FIni : TMemIniFile;
  19. procedure CheckKey(aName, aCode: String);
  20. function getMode: TMode;
  21. procedure ListKeys;
  22. procedure PrintKey(aKey: String);
  23. procedure Usage(const aError: String);
  24. Public
  25. Constructor Create(aOwner : TComponent); override;
  26. Destructor Destroy; override;
  27. Procedure DoRun; override;
  28. end;
  29. Const
  30. SKeys = 'Keys';
  31. Need : array[TMode] of Integer = (0,0,2,1,1,0,0,2);
  32. constructor TAuthenticatorApplication.Create(aOwner: TComponent);
  33. begin
  34. inherited Create(aOwner);
  35. FIni:=TMemIniFile.Create(GetAppConfigFile(False));
  36. end;
  37. destructor TAuthenticatorApplication.Destroy;
  38. begin
  39. FreeAndNil(FIni);
  40. inherited Destroy;
  41. end;
  42. Procedure TAuthenticatorApplication.Usage(const aError : String);
  43. begin
  44. if (aError<>'') then
  45. Writeln('Error: ',aError);
  46. Writeln('Usage: ',ExtractFileName(ParamStr(0)),' [-a|-d|-h|-p|-g|-c|-l] [name [key|Value]');
  47. Writeln('If no options are specified, print key code');
  48. Writeln('-h --help This help text');
  49. Writeln('-a --add Add key with given name and key value');
  50. Writeln('-d --remove Remove key with given name');
  51. Writeln('-g --generate Generate and print new key');
  52. Writeln('-l --list List known keys');
  53. Writeln('-c --check Check code against key for given name');
  54. ExitCode:=Ord(AError<>'')
  55. end;
  56. Function TAuthenticatorApplication.getMode : TMode;
  57. var
  58. aMode : TMode;
  59. begin
  60. aMode:=mPrint;
  61. if HasOption('h','help') then
  62. aMode:=mHelp
  63. else if HasOption('a','add') then
  64. aMode:=mAdd
  65. else if HasOption('g','generate') then
  66. aMode:=mGenerate
  67. else if HasOption('c','check') then
  68. aMode:=mCheck
  69. else if HasOption('r','remove') then
  70. aMode:=mDelete
  71. else if HasOption('l','list') then
  72. aMode:=mList;
  73. result:=aMode;
  74. end;
  75. Procedure TAuthenticatorApplication.CheckKey(aName,aCode : String);
  76. Var
  77. S : String;
  78. aCount : Integer;
  79. begin
  80. S:=FIni.ReadString(SKeys,aName,'');
  81. if S='' then
  82. begin
  83. Writeln('No such key : ',aName);
  84. ExitCode:=1;
  85. end
  86. else
  87. begin
  88. if TOTPValidate(S,StrToIntDef(aCode,-1),1,aCount) then
  89. Writeln('Code OK')
  90. else
  91. begin
  92. Writeln('Code wrong');
  93. ExitCode:=1;
  94. end;
  95. end;
  96. end;
  97. Procedure TAuthenticatorApplication.PrintKey(aKey : String);
  98. Var
  99. S : String;
  100. begin
  101. S:=FIni.ReadString(SKeys,aKey,'');
  102. if S='' then
  103. begin
  104. Writeln('No such key : ',S);
  105. ExitCode:=1;
  106. end
  107. else
  108. Writeln('Token: ',TOTPGenerateToken(S));
  109. end;
  110. Procedure TAuthenticatorApplication.ListKeys;
  111. Var
  112. L : TStrings;
  113. I : Integer;
  114. N,K : String;
  115. begin
  116. L:=TStringList.Create;
  117. try
  118. Fini.ReadSectionValues(SKeys,L);
  119. Writeln('Known keys: ');
  120. For I:=0 to L.Count-1 do
  121. begin
  122. L.GetNameValue(I,N,K);
  123. Writeln(N,' : ',K);
  124. end;
  125. finally
  126. L.Free;
  127. end;
  128. end;
  129. Procedure TAuthenticatorApplication.DoRun;
  130. Const
  131. Opts : String ='harpgcl';
  132. LongOpts : Array of string = ('help','add','remove','print','generate','check','list');
  133. Var
  134. aErr : String;
  135. aMode : TMode;
  136. NonArgs : TStringArray;
  137. begin
  138. Terminate;
  139. aMode:=mError;
  140. aErr:=CheckOptions(Opts,LongOpts);
  141. NonArgs:=GetNonOptions(Opts,LongOpts);
  142. if (aErr='') then
  143. begin
  144. aMode:=GetMode;
  145. if aMode in [mAdd,mDelete,mGenerate] then
  146. if Length(NonArgs)<>Need[aMode] then
  147. begin
  148. aErr:=Format('Need %d arguments, got %d',[Need[aMode],Length(NonArgs)]);
  149. aMode:=mError;
  150. end;
  151. end;
  152. Case aMode of
  153. mError,mHelp:
  154. Usage(aErr);
  155. mAdd:
  156. begin
  157. FIni.WriteString(SKeys,NonArgs[0],NonArgs[1]);
  158. Fini.UpdateFile;
  159. end;
  160. mDelete:
  161. begin
  162. FIni.DeleteKey(SKeys,NonArgs[0]);
  163. Fini.UpdateFile;
  164. end;
  165. mPrint:
  166. begin
  167. PrintKey(NonArgs[0]);
  168. end;
  169. mGenerate:
  170. Writeln(TOTPSharedSecret());
  171. mCheck:
  172. begin
  173. CheckKey(NonArgs[0],NonArgs[1]);
  174. end;
  175. mList:
  176. ListKeys;
  177. end;
  178. end;
  179. begin
  180. CustomApplication:=TAuthenticatorApplication.Create(Nil);
  181. CustomApplication.Initialize;
  182. CustomApplication.Run;
  183. CustomApplication.Free;
  184. end.