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