File: hydra-oracle.c

package info (click to toggle)
hydra 9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 4,008 kB
  • sloc: ansic: 21,638; sh: 2,166; makefile: 110
file content (202 lines) | stat: -rw-r--r-- 6,569 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*

david: code is based on SNORT spo_database.c

tested with :
-instantclient_10_2 on Oracle 10.2.0
-instantclient-basic-linux.*-11.2.0.3.0.zip + instantclient-sdk-linux.*-11.2.0.3.0.zip
on Oracle 9i and on Oracle 11g

*/

#include "hydra-mod.h"

#ifndef LIBORACLE

void dummy_oracle() {
  printf("\n");
}

#else

#include <oci.h>
#include <sys/types.h>

extern char *HYDRA_EXIT;

OCIEnv *o_environment;
OCISvcCtx *o_servicecontext;
OCIBind *o_bind;
OCIError *o_error;
OCIStmt *o_statement;
OCIDefine *o_define;
text o_errormsg[512];
sb4 o_errorcode;

void print_oracle_error(char *err) {
  if (verbose) {
    OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
    fprintf(stderr, "[ERROR] Oracle_error: %s - %s\n", o_errormsg, err);
  }
}

int32_t start_oracle(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE * fp) {
  char *empty = "";
  char *login, *pass, buffer[200], sid[100];

  if (strlen(login = hydra_get_next_login()) == 0)
    login = empty;
  if (strlen(pass = hydra_get_next_password()) == 0)
    pass = empty;

  strncpy(sid, miscptr, sizeof(sid) - 1);
  sid[sizeof(sid) - 1] = 0;
  snprintf(buffer, sizeof(buffer), "//%s:%d/%s", hydra_address2string(ip), port, sid);

  /*

     To use the Easy Connect naming method, PHP must be linked with Oracle 10g or greater Client libraries.
     The Easy Connect string for Oracle 10g is of the form: [//]host_name[:port][/service_name].
     With Oracle 11g, the syntax is: [//]host_name[:port][/service_name][:server_type][/instance_name].
     Service names can be found by running the Oracle utility lsnrctl status on the database server machine.

     The tnsnames.ora file can be in the Oracle Net search path, which includes $ORACLE_HOME/network/admin
     and /etc. Alternatively set TNS_ADMIN so that $TNS_ADMIN/tnsnames.ora is read. Make sure the web
     daemon has read access to the file. 

   */

  if (OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL)) {
    print_oracle_error("OCIInitialize");
    return 4;
  }
  if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL)) {
    print_oracle_error("OCIEnvInit");
    return 4;
  }
  if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL)) {
    print_oracle_error("OCIEnvInit 2");
    return 4;
  }
  if (OCIHandleAlloc(o_environment, (dvoid **) & o_error, OCI_HTYPE_ERROR, (size_t) 0, NULL)) {
    print_oracle_error("OCIHandleAlloc");
    return 4;
  }

  if (OCILogon(o_environment, o_error, &o_servicecontext, (const OraText *) login, strlen(login), (const OraText *) pass, strlen(pass), (const OraText *) buffer, strlen(buffer))) {
    OCIErrorGet(o_error, 1, NULL, &o_errorcode, o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
    //database: oracle_error: ORA-01017: invalid username/password; logon denied
    //database: oracle_error: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
    //database: oracle_error: ORA-28000: the account is locked
    //Failed login attempts is set to 10 by default
    if (verbose) {
      hydra_report(stderr, "[VERBOSE] database: oracle_error: %s\n", o_errormsg);
    }
    if (strstr((const char *) o_errormsg, "ORA-12514") != NULL) {
      hydra_report(stderr, "[ERROR] ORACLE SID is not valid, you should try to enumerate them.\n");
      hydra_completed_pair();
      return 3;
    }
    if (strstr((const char *) o_errormsg, "ORA-28000") != NULL) {
      hydra_report(stderr, "[INFO] ORACLE account %s is locked.\n", login);
      hydra_completed_pair_skip();
      if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
        return 3;
      return 2;
    }

    if (o_error) {
      OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR);
    }

    hydra_completed_pair();
    //by default, set in sqlnet.ora, the trace file is generated in pwd to log any errors happening,
    //as we don't care, we are deleting the file
    //set these parameters to not generate the file
    //LOG_DIRECTORY_CLIENT = /dev/null
    //LOG_FILE_CLIENT = /dev/null

    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 3;
    return 2;
  } else {
    OCILogoff(o_servicecontext, o_error);
    if (o_error) {
      OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR);
    }
    hydra_report_found_host(port, ip, "oracle", fp);
    hydra_completed_pair_found();
  }
  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
    return 3;
  return 1;
}

void service_oracle(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname) {
  int32_t run = 1, next_run = 1, sock = -1;
  int32_t myport = PORT_ORACLE;

  hydra_register_socket(sp);
  if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
    return;

  if ((miscptr == NULL) || (strlen(miscptr) == 0)) {
    //SID is required as miscptr
    hydra_report(stderr, "[ERROR] Oracle SID is required, using ORCL as default\n");
    miscptr = "ORCL";
  }

  while (1) {
    switch (run) {
    case 1:                    /* connect and service init function */
      if (sock >= 0)
        sock = hydra_disconnect(sock);
      if (port != 0)
        myport = port;
      sock = hydra_connect_tcp(ip, myport);
      port = myport;

      if (sock < 0) {
        if (verbose || debug)
          hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int32_t) getpid());
        hydra_child_exit(1);
      }
      next_run = 2;
      break;
    case 2:
      next_run = start_oracle(sock, ip, port, options, miscptr, fp);
      hydra_child_exit(0);
      break;
    case 3:                    /* clean exit */
      if (sock >= 0)
        sock = hydra_disconnect(sock);
      unlink("sqlnet.log");
      hydra_child_exit(0);
      return;
    default:
      hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
      hydra_child_exit(2);
    }
    run = next_run;
  }
}

#endif

int32_t service_oracle_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE * fp, int32_t port, char *hostname) {
  // called before the childrens are forked off, so this is the function
  // which should be filled if initial connections and service setup has to be
  // performed once only.
  //
  // fill if needed.
  // 
  // return codes:
  //   0 all OK
  //   -1  error, hydra will exit, so print a good error message here

  return 0;
}

void usage_oracle(const char* service) {
  printf("Module oracle / ora is optionally taking the ORACLE SID, default is \"ORCL\"\n\n");
}