1 module authentication;
2 
3 import core.stdc.string : memset;
4 import std.stdio;
5 import std.algorithm.searching;
6 import std.exception;
7 
8 import libssh.session;
9 import libssh.utils;
10 import libssh.errors;
11 
12 AuthState authenticateKbdint(SSHSession session, string password) {
13     auto err = session.userauthKeyboardInteractive(null);
14     while (err == AuthState.Info) {
15         auto name = session.userauthKeyboardInteractiveGetName();
16         auto instruction = session.userauthKeyboardInteractiveGetInstruction();
17         auto n = session.userauthKeyboardInteractiveGetNPrompts();
18 
19         if (name !is null && name.length > 0) {
20             stdout.writefln("%s", name);
21         }
22 
23         if (instruction !is null && instruction.length > 0) {
24             stdout.writefln("%s", instruction);
25         }
26 
27         for (int i = 0; i < n; i++) {
28             bool echo;
29             auto prompt = session.userauthKeyboardInteractiveGetPrompt(i, echo);
30 
31             if (echo) {
32                 stdout.writefln("%s", prompt);
33 
34                 auto buffer = stdin.readln()[0 .. $ - 1];
35                 session.userauthKeyboardInteractiveSetAnswer(i, buffer);
36             } else {
37                 string answer;
38                 char[] buffer;
39                 scope(exit) if (buffer !is null) memset(buffer.ptr, 0, buffer.length);
40 
41                 if (password !is null && prompt.canFind("Password:")) {
42                     answer = password;
43                 } else {
44                     buffer = getPassword!(128)(prompt, false, false);
45                     if (buffer is null) {
46                         throw new SSHException("Error while reading password from user");
47                     }
48                     answer = assumeUnique(buffer);
49                 }
50 
51                 session.userauthKeyboardInteractiveSetAnswer(i, answer);
52             }
53         }
54         err = session.userauthKeyboardInteractive(null);
55     }
56     return err;
57 }
58 
59 AuthState authenticateConsole(SSHSession session) {
60     // Try to authenticate
61     AuthState rc = session.userauthNone(null);
62 
63     auto method = session.userauthList(null);
64 
65     while (rc != AuthState.Success) {
66         if ((method & AuthMethod.GSSAPIMic) != 0) {
67             rc = session.userauthGSSAPI();
68             if (rc == AuthState.Success) {
69                 break;
70             }
71         }
72 
73         // Try to authenticate with public key first
74         if ((method & AuthMethod.PublicKey) != 0) {
75             rc = session.userauthPublicKeyAuto(null, null);
76             if (rc == AuthState.Success) {
77                 break;
78             }
79         }
80 
81         // Try to authenticate with keyboard interactive";
82         if ((method & AuthMethod.Interactive) != 0) {
83             rc = authenticateKbdint(session, null);
84             if (rc == AuthState.Success) {
85                 break;
86             }
87         }
88 
89         auto password = getPassword!(128)("Password: ", false, false);
90         if (password is null) {
91             throw new SSHException("Error while reading password from user");
92         }
93 
94         // Try to authenticate with password
95         if ((method & AuthMethod.Password) != 0) {
96             rc = session.userauthPassword(null, assumeUnique(password));
97             if (rc == AuthState.Success) {
98                 break;
99             }
100         }
101         memset(password.ptr, 0, password.length);
102     }
103 
104     auto banner = session.issueBanner();
105     if (banner !is null) {
106         stdout.writefln("%s", banner);
107     }
108     return rc;
109 }