spelling fixes
[exim.git] / src / src / lookups / oracle.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2015 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8 /* Interface to an Oracle database. This code was originally supplied by
9 Paul Kelly, but I have hacked it around for various reasons, and tried to add
10 some comments from my position of Oracle ignorance. */
11
12
13 #include "../exim.h"
14
15
16 /* The Oracle system headers */
17
18 #include <oratypes.h>
19 #include <ocidfn.h>
20 #include <ocikpr.h>
21
22 #define PARSE_NO_DEFER           0     /* parse straight away */
23 #define PARSE_V7_LNG             2
24 #define MAX_ITEM_BUFFER_SIZE  1024     /* largest size of a cell of data */
25 #define MAX_SELECT_LIST_SIZE    32     /* maximum number of columns (not rows!) */
26
27 /* Paul's comment on this was "change this to 512 for 64bit cpu", but I don't
28 understand why. The Oracle manual just asks for 256 bytes.
29
30 That was years ago. Jin Choi suggested (March 2007) that this change should
31 be made in the source, as at worst it wastes 256 bytes, and it saves people
32 having to discover about this for themselves as more and more systems are
33 64-bit. So I have changed 256 to 512. */
34
35 #define HDA_SIZE 512
36
37 /* Internal/external datatype codes */
38
39 #define NUMBER_TYPE              2
40 #define INT_TYPE                 3
41 #define FLOAT_TYPE               4
42 #define STRING_TYPE              5
43 #define ROWID_TYPE              11
44 #define DATE_TYPE               12
45
46 /*  ORACLE error codes used in demonstration programs */
47
48 #define VAR_NOT_IN_LIST       1007
49 #define NO_DATA_FOUND         1403
50
51 typedef struct Ora_Describe {
52   sb4   dbsize;
53   sb2   dbtype;
54   sb1   buf[MAX_ITEM_BUFFER_SIZE];
55   sb4   buflen;
56   sb4   dsize;
57   sb2   precision;
58   sb2   scale;
59   sb2   nullok;
60 } Ora_Describe;
61
62 typedef struct Ora_Define {
63   ub1   buf[MAX_ITEM_BUFFER_SIZE];
64   float flt_buf;
65   sword int_buf;
66   sb2   indp;
67   ub2   col_retlen, col_retcode;
68 } Ora_Define;
69
70 /* Structure and anchor for caching connections. */
71
72 typedef struct oracle_connection {
73   struct oracle_connection *next;
74   uschar *server;
75   struct cda_def *handle;
76   void   *hda_mem;
77 } oracle_connection;
78
79 static oracle_connection *oracle_connections = NULL;
80
81
82
83
84
85 /*************************************************
86 *        Set up message after error              *
87 *************************************************/
88
89 /* Sets up a message from a local string plus whatever Oracle gives.
90
91 Arguments:
92   oracle_handle   the handle of the connection
93   rc              the return code
94   msg             local text message
95 */
96
97 static uschar *
98 oracle_error(struct cda_def *oracle_handle, int rc, uschar *msg)
99 {
100 uschar tmp[1024];
101 oerhms(oracle_handle, rc, tmp, sizeof(tmp));
102 return string_sprintf("ORACLE %s: %s", msg, tmp);
103 }
104
105
106
107 /*************************************************
108 *     Describe and define the select list items  *
109 *************************************************/
110
111 /* Figures out sizes, types, and numbers.
112
113 Arguments:
114   cda        the connection
115   def
116   desc       descriptions put here
117
118 Returns:     number of fields
119 */
120
121 static sword
122 describe_define(Cda_Def *cda, Ora_Define *def, Ora_Describe *desc)
123 {
124 sword col, deflen, deftyp;
125 static ub1 *defptr;
126 static sword numwidth = 8;
127
128 /* Describe the select-list items. */
129
130 for (col = 0; col < MAX_SELECT_LIST_SIZE; col++)
131   {
132   desc[col].buflen = MAX_ITEM_BUFFER_SIZE;
133
134   if (odescr(cda, col + 1, &desc[col].dbsize,
135              &desc[col].dbtype, &desc[col].buf[0],
136              &desc[col].buflen, &desc[col].dsize,
137              &desc[col].precision, &desc[col].scale,
138              &desc[col].nullok) != 0)
139     {
140     /* Break on end of select list. */
141     if (cda->rc == VAR_NOT_IN_LIST) break; else return -1;
142     }
143
144   /* Adjust sizes and types for display, handling NUMBER with scale as float. */
145
146   if (desc[col].dbtype == NUMBER_TYPE)
147     {
148     desc[col].dbsize = numwidth;
149     if (desc[col].scale != 0)
150       {
151       defptr = (ub1 *)&def[col].flt_buf;
152       deflen = (sword) sizeof(float);
153       deftyp = FLOAT_TYPE;
154       desc[col].dbtype = FLOAT_TYPE;
155       }
156     else
157       {
158       defptr = (ub1 *)&def[col].int_buf;
159       deflen = (sword) sizeof(sword);
160       deftyp = INT_TYPE;
161       desc[col].dbtype = INT_TYPE;
162       }
163     }
164   else
165     {
166     if (desc[col].dbtype == DATE_TYPE)
167         desc[col].dbsize = 9;
168     if (desc[col].dbtype == ROWID_TYPE)
169         desc[col].dbsize = 18;
170     defptr = def[col].buf;
171     deflen = desc[col].dbsize > MAX_ITEM_BUFFER_SIZE ?
172       MAX_ITEM_BUFFER_SIZE : desc[col].dbsize + 1;
173     deftyp = STRING_TYPE;
174     desc[col].dbtype = STRING_TYPE;
175     }
176
177   /* Define an output variable */
178
179   if (odefin(cda, col + 1,
180              defptr, deflen, deftyp,
181              -1, &def[col].indp, (text *) 0, -1, -1,
182              &def[col].col_retlen,
183              &def[col].col_retcode) != 0)
184     return -1;
185   }  /* Loop for each column */
186
187 return col;
188 }
189
190
191
192 /*************************************************
193 *              Open entry point                  *
194 *************************************************/
195
196 /* See local README for interface description. */
197
198 static void *
199 oracle_open(uschar *filename, uschar **errmsg)
200 {
201 return (void *)(1);    /* Just return something non-null */
202 }
203
204
205
206 /*************************************************
207 *               Tidy entry point                 *
208 *************************************************/
209
210 /* See local README for interface description. */
211
212 static void
213 oracle_tidy(void)
214 {
215 oracle_connection *cn;
216 while ((cn = oracle_connections) != NULL)
217   {
218   oracle_connections = cn->next;
219   DEBUG(D_lookup) debug_printf("close ORACLE connection: %s\n", cn->server);
220   ologof(cn->handle);
221   }
222 }
223
224
225
226 /*************************************************
227 *        Internal search function                *
228 *************************************************/
229
230 /* This function is called from the find entry point to do the search for a
231 single server.
232
233 Arguments:
234   query        the query string
235   server       the server string
236   resultptr    where to store the result
237   errmsg       where to point an error message
238   defer_break  TRUE if no more servers are to be tried after DEFER
239
240 The server string is of the form "host/dbname/user/password", for compatibility
241 with MySQL and pgsql, but at present, the dbname is not used. This string is in
242 a nextinlist temporary buffer, so can be overwritten.
243
244 Returns:       OK, FAIL, or DEFER
245 */
246
247 static int
248 perform_oracle_search(uschar *query, uschar *server, uschar **resultptr,
249   uschar **errmsg, BOOL *defer_break)
250 {
251 Cda_Def *cda = NULL;
252 struct cda_def *oracle_handle = NULL;
253 Ora_Describe *desc = NULL;
254 Ora_Define *def = NULL;
255 void *hda = NULL;
256
257 int i;
258 int yield = DEFER;
259 unsigned int num_fields = 0;
260 gstring * result = NULL;
261 oracle_connection *cn = NULL;
262 uschar *server_copy = NULL;
263 uschar *sdata[4];
264
265 /* Disaggregate the parameters from the server argument. The order is host,
266 database, user, password. We can write to the string, since it is in a
267 nextinlist temporary buffer. The copy of the string that is used for caching
268 has the password removed. This copy is also used for debugging output. */
269
270 for (i = 3; i > 0; i--)
271   {
272   uschar *pp = Ustrrchr(server, '/');
273   if (pp == NULL)
274     {
275     *errmsg = string_sprintf("incomplete ORACLE server data: %s", server);
276     *defer_break = TRUE;
277     return DEFER;
278     }
279   *pp++ = 0;
280   sdata[i] = pp;
281   if (i == 3) server_copy = string_copy(server);  /* sans password */
282   }
283 sdata[0] = server;   /* What's left at the start */
284
285 /* If the database is the empty string, set it NULL - the query must then
286 define it. */
287
288 if (sdata[1][0] == 0) sdata[1] = NULL;
289
290 /* See if we have a cached connection to the server */
291
292 for (cn = oracle_connections; cn; cn = cn->next)
293   if (strcmp(cn->server, server_copy) == 0)
294     {
295     oracle_handle = cn->handle;
296     hda = cn->hda_mem;
297     break;
298     }
299
300 /* If no cached connection, we must set one up */
301
302 if (!cn)
303   {
304   DEBUG(D_lookup) debug_printf("ORACLE new connection: host=%s database=%s "
305     "user=%s\n", sdata[0], sdata[1], sdata[2]);
306
307   /* Get store for a new connection, initialize it, and connect to the server */
308
309    oracle_handle = store_get(sizeof(struct cda_def));
310    hda = store_get(HDA_SIZE);
311    memset(hda,'\0',HDA_SIZE);
312
313   /*
314    * Perform a default (blocking) login
315    *
316    * sdata[0] = tnsname (service name - typically host name)
317    * sdata[1] = dbname - not used at present
318    * sdata[2] = username
319    * sdata[3] = passwd
320    */
321
322   if(olog(oracle_handle, hda, sdata[2], -1, sdata[3], -1, sdata[0], -1,
323          (ub4)OCI_LM_DEF) != 0)
324     {
325     *errmsg = oracle_error(oracle_handle, oracle_handle->rc,
326       US"connection failed");
327     *defer_break = FALSE;
328     goto ORACLE_EXIT_NO_VALS;
329     }
330
331   /* Add the connection to the cache */
332
333   cn = store_get(sizeof(oracle_connection));
334   cn->server = server_copy;
335   cn->handle = oracle_handle;
336   cn->next = oracle_connections;
337   cn->hda_mem = hda;
338   oracle_connections = cn;
339   }
340
341 /* Else use a previously cached connection - we can write to the server string
342 to obliterate the password because it is in a nextinlist temporary buffer. */
343
344 else
345   {
346   DEBUG(D_lookup)
347     debug_printf("ORACLE using cached connection for %s\n", server_copy);
348   }
349
350 /* We have a connection. Open a cursor and run the query */
351
352 cda = store_get(sizeof(Cda_Def));
353
354 if (oopen(cda, oracle_handle, (text *)0, -1, -1, (text *)0, -1) != 0)
355   {
356   *errmsg = oracle_error(oracle_handle, cda->rc, "failed to open cursor");
357   *defer_break = FALSE;
358   goto ORACLE_EXIT_NO_VALS;
359   }
360
361 if (oparse(cda, (text *)query, (sb4) -1,
362       (sword)PARSE_NO_DEFER, (ub4)PARSE_V7_LNG) != 0)
363   {
364   *errmsg = oracle_error(oracle_handle, cda->rc, "query failed");
365   *defer_break = FALSE;
366   oclose(cda);
367   goto ORACLE_EXIT_NO_VALS;
368   }
369
370 /* Find the number of fields returned and sort out their types. If the number
371 is one, we don't add field names to the data. Otherwise we do. */
372
373 def = store_get(sizeof(Ora_Define)*MAX_SELECT_LIST_SIZE);
374 desc = store_get(sizeof(Ora_Describe)*MAX_SELECT_LIST_SIZE);
375
376 if ((num_fields = describe_define(cda,def,desc)) == -1)
377   {
378   *errmsg = oracle_error(oracle_handle, cda->rc, "describe_define failed");
379   *defer_break = FALSE;
380   goto ORACLE_EXIT;
381   }
382
383 if (oexec(cda)!=0)
384   {
385   *errmsg = oracle_error(oracle_handle, cda->rc, "oexec failed");
386   *defer_break = FALSE;
387   goto ORACLE_EXIT;
388   }
389
390 /* Get the fields and construct the result string. If there is more than one
391 row, we insert '\n' between them. */
392
393 while (cda->rc != NO_DATA_FOUND)  /* Loop for each row */
394   {
395   ofetch(cda);
396   if(cda->rc == NO_DATA_FOUND) break;
397
398   if (result) result = string_catn(result, "\n", 1);
399
400   /* Single field - just add on the data */
401
402   if (num_fields == 1)
403     result = string_catn(result, def[0].buf, def[0].col_retlen);
404
405   /* Multiple fields - precede by file name, removing {lead,trail}ing WS */
406
407   else for (i = 0; i < num_fields; i++)
408     {
409     int slen;
410     uschar *s = US desc[i].buf;
411
412     while (*s != 0 && isspace(*s)) s++;
413     slen = Ustrlen(s);
414     while (slen > 0 && isspace(s[slen-1])) slen--;
415     result = string_catn(result, s, slen);
416     result = string_catn(result, US"=", 1);
417
418     /* int and float type won't ever need escaping. Otherwise, quote the value
419     if it contains spaces or is empty. */
420
421     if (desc[i].dbtype != INT_TYPE && desc[i].dbtype != FLOAT_TYPE &&
422        (def[i].buf[0] == 0 || strchr(def[i].buf, ' ') != NULL))
423       {
424       int j;
425       result = string_catn(result, "\"", 1);
426       for (j = 0; j < def[i].col_retlen; j++)
427         {
428         if (def[i].buf[j] == '\"' || def[i].buf[j] == '\\')
429           result = string_catn(result, "\\", 1);
430         result = string_catn(result, def[i].buf+j, 1);
431         }
432       result = string_catn(result, "\"", 1);
433       }
434
435     else switch(desc[i].dbtype)
436       {
437       case INT_TYPE:
438         result = string_cat(result, string_sprintf("%d", def[i].int_buf));
439         break;
440
441       case FLOAT_TYPE:
442         result = string_cat(result, string_sprintf("%f", def[i].flt_buf));
443         break;
444
445       case STRING_TYPE:
446         result = string_catn(result, def[i].buf, def[i].col_retlen);
447         break;
448
449       default:
450         *errmsg = string_sprintf("ORACLE: unknown field type %d", desc[i].dbtype);
451         *defer_break = FALSE;
452         result = NULL;
453         goto ORACLE_EXIT;
454       }
455
456     result = string_catn(result, " ", 1);
457     }
458   }
459
460 /* If result is NULL then no data has been found and so we return FAIL.
461 Otherwise, we must terminate the string which has been built; string_cat()
462 always leaves enough room for a terminating zero. */
463
464 if (!result)
465   {
466   yield = FAIL;
467   *errmsg = "ORACLE: no data found";
468   }
469 else
470   store_reset(result->s + result->ptr + 1);
471
472 /* Get here by goto from various error checks. */
473
474 ORACLE_EXIT:
475
476 /* Close the cursor; don't close the connection, as it is cached. */
477
478 oclose(cda);
479
480 ORACLE_EXIT_NO_VALS:
481
482 /* Non-NULL result indicates a successful result */
483
484 if (result)
485   {
486   *resultptr = string_from_gstring(result);
487   return OK;
488   }
489 else
490   {
491   DEBUG(D_lookup) debug_printf("%s\n", *errmsg);
492   return yield;      /* FAIL or DEFER */
493   }
494 }
495
496
497
498
499 /*************************************************
500 *               Find entry point                 *
501 *************************************************/
502
503 /* See local README for interface description. The handle and filename
504 arguments are not used. Loop through a list of servers while the query is
505 deferred with a retryable error. */
506
507 static int
508 oracle_find(void *handle, uschar *filename, uschar *query, int length,
509   uschar **result, uschar **errmsg, uint *do_cache)
510 {
511 int sep = 0;
512 uschar *server;
513 uschar *list = oracle_servers;
514 uschar buffer[512];
515
516 do_cache = do_cache;   /* Placate picky compilers */
517
518 DEBUG(D_lookup) debug_printf("ORACLE query: %s\n", query);
519
520 while ((server = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
521   {
522   BOOL defer_break;
523   int rc = perform_oracle_search(query, server, result, errmsg, &defer_break);
524   if (rc != DEFER || defer_break) return rc;
525   }
526
527 if (oracle_servers == NULL)
528   *errmsg = "no ORACLE servers defined (oracle_servers option)";
529
530 return DEFER;
531 }
532
533
534
535 /*************************************************
536 *               Quote entry point                *
537 *************************************************/
538
539 /* The only characters that need to be quoted (with backslash) are newline,
540 tab, carriage return, backspace, backslash itself, and the quote characters.
541 Percent and underscore are not escaped. They are only special in contexts where
542 they can be wild cards, and this isn't usually the case for data inserted from
543 messages, since that isn't likely to be treated as a pattern of any kind.
544
545 Arguments:
546   s          the string to be quoted
547   opt        additional option text or NULL if none
548
549 Returns:     the processed string or NULL for a bad option
550 */
551
552 static uschar *
553 oracle_quote(uschar *s, uschar *opt)
554 {
555 register int c;
556 int count = 0;
557 uschar *t = s;
558 uschar *quoted;
559
560 if (opt != NULL) return NULL;    /* No options are recognized */
561
562 while ((c = *t++) != 0)
563   if (strchr("\n\t\r\b\'\"\\", c) != NULL) count++;
564
565 if (count == 0) return s;
566 t = quoted = store_get((int)strlen(s) + count + 1);
567
568 while ((c = *s++) != 0)
569   {
570   if (strchr("\n\t\r\b\'\"\\", c) != NULL)
571     {
572     *t++ = '\\';
573     switch(c)
574       {
575       case '\n': *t++ = 'n';
576       break;
577       case '\t': *t++ = 't';
578       break;
579       case '\r': *t++ = 'r';
580       break;
581       case '\b': *t++ = 'b';
582       break;
583       default:   *t++ = c;
584       break;
585       }
586     }
587   else *t++ = c;
588   }
589
590 *t = 0;
591 return quoted;
592 }
593
594
595 /*************************************************
596 *         Version reporting entry point          *
597 *************************************************/
598
599 /* See local README for interface description. */
600
601 #include "../version.h"
602
603 void
604 oracle_version_report(FILE *f)
605 {
606 #ifdef DYNLOOKUP
607 fprintf(f, "Library version: Oracle: Exim version %s\n", EXIM_VERSION_STR);
608 #endif
609 }
610
611
612 static lookup_info _lookup_info = {
613   US"oracle",                    /* lookup name */
614   lookup_querystyle,             /* query-style lookup */
615   oracle_open,                   /* open function */
616   NULL,                          /* check function */
617   oracle_find,                   /* find function */
618   NULL,                          /* no close function */
619   oracle_tidy,                   /* tidy function */
620   oracle_quote,                  /* quoting function */
621   oracle_version_report          /* version reporting */
622 };
623
624 #ifdef DYNLOOKUP
625 #define oracle_lookup_module_info _lookup_module_info
626 #endif
627
628 static lookup_info *_lookup_list[] = { &_lookup_info };
629 lookup_module_info oracle_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
630
631 /* End of lookups/oracle.c */