1 
2 /*
3  libssh is available at http://www.libssh.org
4  current version is 0.4.8
5  If you want support for ssh v1 protocol, you
6  have to add option -DWITH_SSH1=On in the cmake
7 */
8 
9 #include "hydra-mod.h"
10 #ifndef LIBSSH
dummy_sshkey()11 void dummy_sshkey() { printf("\n"); }
12 #else
13 
14 #include <libssh/libssh.h>
15 
16 #if LIBSSH_VERSION_MAJOR >= 0 && LIBSSH_VERSION_MINOR >= 4
17 
18 extern ssh_session session;
19 extern char *HYDRA_EXIT;
20 extern int32_t new_session;
21 
start_sshkey(int32_t s,char * ip,int32_t port,unsigned char options,char * miscptr,FILE * fp)22 int32_t start_sshkey(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp) {
23   char *empty = "";
24   char *login, *key, keep_login[300];
25   int32_t auth_state = 0, rc = 0;
26   ssh_private_key privkey;
27 
28   if (strlen(login = hydra_get_next_login()) == 0)
29     login = empty;
30   if (strlen(key = hydra_get_next_password()) == 0)
31     key = empty;
32 
33   if (new_session) {
34     if (session) {
35       ssh_disconnect(session);
36       ssh_finalize();
37       ssh_free(session);
38     }
39 
40     session = ssh_new();
41     ssh_options_set(session, SSH_OPTIONS_PORT, &port);
42     ssh_options_set(session, SSH_OPTIONS_HOST, hydra_address2string(ip));
43     ssh_options_set(session, SSH_OPTIONS_USER, login);
44     ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
45     ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
46     if (ssh_connect(session) != 0) {
47       // if the connection was drop, exit and let hydra main handle it
48       if (verbose)
49         hydra_report(stderr, "[ERROR] could not connect to target port %d\n", port);
50       return 3;
51     }
52 
53     if ((rc = ssh_userauth_none(session, NULL)) == SSH_AUTH_ERROR) {
54       return 3;
55     } else if (rc == SSH_AUTH_SUCCESS) {
56       hydra_report_found_host(port, ip, "sshkey", fp);
57       hydra_completed_pair_found();
58       if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
59         return 2;
60       else
61         return 1;
62     }
63   } else
64     new_session = 1;
65 
66   auth_state = ssh_auth_list(session);
67   if ((auth_state & SSH_AUTH_METHOD_PUBLICKEY) > 0) {
68     privkey = privatekey_from_file(session, key, 0, NULL);
69     if (!privkey) {
70       hydra_report(stderr, "[ERROR] skipping invalid private key: \"%s\"\n", key);
71       hydra_completed_pair();
72       if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
73         return 2;
74 
75       return 1;
76     }
77     auth_state = ssh_userauth_pubkey(session, NULL, NULL, privkey);
78   } else {
79     return 4;
80   }
81 
82   if (auth_state == SSH_AUTH_ERROR) {
83     new_session = 1;
84     return 1;
85   }
86 
87   if (auth_state == SSH_AUTH_SUCCESS || auth_state == SSH_AUTH_PARTIAL) {
88     hydra_report_found_host(port, ip, "sshkey", fp);
89     hydra_completed_pair_found();
90     if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
91       return 2;
92     return 1;
93   } else {
94     strncpy(keep_login, login, sizeof(keep_login) - 1);
95     keep_login[sizeof(keep_login) - 1] = '\0';
96     hydra_completed_pair();
97     if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
98       return 2;
99     login = hydra_get_next_login();
100     if (strcmp(login, keep_login) == 0)
101       new_session = 0;
102     return 1;
103   }
104 
105   /* not reached */
106   return 1;
107 }
108 
service_sshkey(char * ip,int32_t sp,unsigned char options,char * miscptr,FILE * fp,int32_t port,char * hostname)109 void service_sshkey(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
110   int32_t run = 1, next_run = 1, sock = -1;
111 
112   hydra_register_socket(sp);
113   if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
114     return;
115   while (1) {
116     switch (run) {
117     case 1: /* connect and service init function */
118       next_run = start_sshkey(sock, ip, port, options, miscptr, fp);
119       break;
120     case 2:
121       ssh_disconnect(session);
122       ssh_finalize();
123       ssh_free(session);
124       hydra_child_exit(0);
125       break;
126     case 3:
127       ssh_disconnect(session);
128       ssh_finalize();
129       ssh_free(session);
130       fprintf(stderr, "[ERROR] ssh protocol error\n");
131       hydra_child_exit(2);
132       break;
133     case 4:
134       ssh_disconnect(session);
135       ssh_finalize();
136       ssh_free(session);
137       fprintf(stderr, "[ERROR] ssh target does not support pubkey auth\n");
138       hydra_child_exit(2);
139       break;
140     default:
141       ssh_disconnect(session);
142       ssh_finalize();
143       ssh_free(session);
144       hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
145       hydra_child_exit(2);
146     }
147     run = next_run;
148   }
149 }
150 #else
151 #error "You are not using at least v0.4.x. Download from http://www.libssh.org and add -DWITH_SSH1=On in cmake to enable SSH v1 support"
152 #endif
153 #endif
154 
service_sshkey_init(char * ip,int32_t sp,unsigned char options,char * miscptr,FILE * fp,int32_t port,char * hostname)155 int32_t service_sshkey_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
156   // called before the childrens are forked off, so this is the function
157   // which should be filled if initial connections and service setup has to be
158   // performed once only.
159   //
160   // fill if needed.
161   //
162   // return codes:
163   //   0 all OK
164   //   -1  error, hydra will exit, so print a good error message here
165 
166   return 0;
167 }
168 
usage_sshkey(const char * service)169 void usage_sshkey(const char *service) {
170   printf("Module sshkey does not provide additional options, although the "
171          "semantic for\n"
172          "options -p and -P is changed:\n"
173          "  -p expects a path to an unencrypted private key in PEM format.\n"
174          "  -P expects a filename containing a list of path to some unencrypted\n"
175          "     private keys in PEM format.\n\n");
176 }
177