1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9/*
10 * author Martin Kersten, Fabian Groffen
11 * Client Management
12 * Each online client is represented with an entry in the clients table.
13 * The client may inspect his record at run-time and partially change its properties.
14 * The administrator sees all client records and has the right to adjust global properties.
15 */
16
17
18#include "monetdb_config.h"
19#include "clients.h"
20#include "mcrypt.h"
21#include "mal_scenario.h"
22#include "mal_instruction.h"
23#include "mal_runtime.h"
24#include "mal_client.h"
25#include "mal_authorize.h"
26#include "mal_private.h"
27#include "mtime.h"
28
29static int
30pseudo(bat *ret, BAT *b, str X1,str X2) {
31 char buf[BUFSIZ];
32 snprintf(buf,BUFSIZ,"%s_%s", X1,X2);
33 if (BBPindex(buf) <= 0 && BBPrename(b->batCacheid, buf) != 0)
34 return -1;
35 if (BATroles(b,X2) != GDK_SUCCEED)
36 return -1;
37 *ret = b->batCacheid;
38 BBPkeepref(*ret);
39 return 0;
40}
41
42str
43CLTsetListing(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
44{
45 (void) mb;
46 *getArgReference_int(stk,pci,0) = cntxt->listing;
47 cntxt->listing = *getArgReference_int(stk,pci,1);
48 return MAL_SUCCEED;
49}
50
51str
52CLTgetClientId(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
53{
54 (void) mb;
55 if(cntxt - mal_clients < 0 || cntxt - mal_clients >= MAL_MAXCLIENTS)
56 throw(MAL, "clients.getClientId", "Illegal client index");
57 *getArgReference_int(stk,pci,0) = (int) (cntxt - mal_clients);
58 return MAL_SUCCEED;
59}
60
61str
62CLTgetScenario(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
63{
64 (void) mb;
65 if (cntxt->scenario)
66 *getArgReference_str(stk,pci,0) = GDKstrdup(cntxt->scenario);
67 else
68 *getArgReference_str(stk,pci,0) = GDKstrdup("nil");
69 if(*getArgReference_str(stk,pci,0) == NULL)
70 throw(MAL, "clients.getScenario", SQLSTATE(HY001) MAL_MALLOC_FAIL);
71 return MAL_SUCCEED;
72}
73
74str
75CLTsetScenario(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
76{
77 str msg = MAL_SUCCEED;
78
79 (void) mb;
80 msg = setScenario(cntxt, *getArgReference_str(stk,pci,1));
81 *getArgReference_str(stk,pci,0) = 0;
82 if (msg == NULL) {
83 *getArgReference_str(stk,pci,0) = GDKstrdup(cntxt->scenario);
84 if(*getArgReference_str(stk,pci,0) == NULL)
85 throw(MAL, "clients.setScenario", SQLSTATE(HY001) MAL_MALLOC_FAIL);
86 }
87 return msg;
88}
89
90static void
91CLTtimeConvert(time_t l, char *s)
92{
93 struct tm localt;
94
95#ifdef HAVE_LOCALTIME_R
96 (void) localtime_r(&l, &localt);
97#else
98 /* race condition: return value could be
99 * overwritten in parallel thread before
100 * assignment complete */
101 localt = *localtime(&l);
102#endif
103
104#ifdef HAVE_ASCTIME_R3
105 asctime_r(&localt, s, 26);
106#else
107#ifdef HAVE_ASCTIME_R
108 asctime_r(&localt, s);
109#else
110 /* race condition: return value could be
111 * overwritten in parallel thread before copy
112 * complete, however on Windows, asctime is
113 * thread-safe */
114 strcpy_len(s, asctime(&localt), 26);
115#endif
116#endif
117 s[24] = 0; /* remove newline */
118}
119
120str
121CLTInfo(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
122{
123 bat *ret= getArgReference_bat(stk,pci,0);
124 bat *ret2= getArgReference_bat(stk,pci,0);
125 BAT *b = COLnew(0, TYPE_str, 12, TRANSIENT);
126 BAT *bn = COLnew(0, TYPE_str, 12, TRANSIENT);
127 char buf[32]; /* 32 bytes are enough */
128
129 (void) mb;
130 if (b == 0 || bn == 0){
131 if ( b != 0) BBPunfix(b->batCacheid);
132 if ( bn != 0) BBPunfix(bn->batCacheid);
133 throw(MAL, "clients.info", SQLSTATE(HY001) MAL_MALLOC_FAIL);
134 }
135
136 (void) snprintf(buf, sizeof(buf), ""LLFMT"", (lng) cntxt->user);
137 if (BUNappend(b, "user", false) != GDK_SUCCEED ||
138 BUNappend(bn, buf, false) != GDK_SUCCEED)
139 goto bailout;
140
141 if (BUNappend(b, "scenario", false) != GDK_SUCCEED ||
142 BUNappend(bn, cntxt->scenario, false) != GDK_SUCCEED)
143 goto bailout;
144
145 (void) snprintf(buf, sizeof(buf), "%d", cntxt->listing);
146 if (BUNappend(b, "listing", false) != GDK_SUCCEED ||
147 BUNappend(bn, buf, false) != GDK_SUCCEED)
148 goto bailout;
149
150 (void) snprintf(buf, sizeof(buf), "%d", cntxt->debug);
151 if (BUNappend(b, "debug", false) != GDK_SUCCEED ||
152 BUNappend(bn, buf, false) != GDK_SUCCEED)
153 goto bailout;
154
155 CLTtimeConvert(cntxt->login, buf);
156 if (BUNappend(b, "login", false) != GDK_SUCCEED ||
157 BUNappend(bn, buf, false) != GDK_SUCCEED)
158 goto bailout;
159 if (pseudo(ret,b,"client","info"))
160 goto bailout;
161 BBPkeepref(*ret2= bn->batCacheid);
162 return MAL_SUCCEED;
163
164bailout:
165 BBPunfix(b->batCacheid);
166 BBPunfix(bn->batCacheid);
167 throw(MAL, "clients.info", SQLSTATE(HY001) MAL_MALLOC_FAIL);
168}
169
170str
171CLTLogin(bat *nme, bat *ret)
172{
173 BAT *b = COLnew(0, TYPE_str, 12, TRANSIENT);
174 BAT *u = COLnew(0, TYPE_oid, 12, TRANSIENT);
175 int i;
176 char s[32];
177
178 if (b == 0 || u == 0)
179 goto bailout;
180
181 for (i = 0; i < MAL_MAXCLIENTS; i++) {
182 Client c = mal_clients+i;
183 if (c->mode >= RUNCLIENT && !is_oid_nil(c->user)) {
184 CLTtimeConvert(c->login, s);
185 if (BUNappend(b, s, false) != GDK_SUCCEED ||
186 BUNappend(u, &c->user, false) != GDK_SUCCEED)
187 goto bailout;
188 }
189 }
190 if (pseudo(ret,b,"client","login") ||
191 pseudo(nme,u,"client","name"))
192 goto bailout;
193 return MAL_SUCCEED;
194
195bailout:
196 BBPreclaim(b);
197 BBPreclaim(u);
198 throw(MAL, "clients.getLogins", SQLSTATE(HY001) MAL_MALLOC_FAIL);
199}
200
201str
202CLTquit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
203{
204 int id;
205 (void) mb; /* fool compiler */
206
207 if ( pci->argc==2)
208 id = *getArgReference_int(stk,pci,1);
209 else id =cntxt->idx;
210
211 if ( !(cntxt->user == MAL_ADMIN || mal_clients[id].user == cntxt->user) )
212 throw(MAL, "client.quit", INVCRED_ACCESS_DENIED);
213
214 /* A user can only quite a session under the same id */
215 if ( cntxt->idx == mal_clients[id].idx)
216 mal_clients[id].mode = FINISHCLIENT;
217 else
218 throw(MAL, "client.quit", INVCRED_ACCESS_DENIED);
219 return MAL_SUCCEED;
220}
221
222/* Stopping a client in a softmanner by setting the time out marker */
223str
224CLTstop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
225{
226 int id = *getArgReference_int(stk,pci,1);
227
228 (void) mb;
229 if (cntxt->user == mal_clients[id].user || cntxt->user == MAL_ADMIN)
230 mal_clients[id].querytimeout = 1; /* stop client in one microsecond */
231 /* this forces the designated client to stop at the next instruction */
232 return MAL_SUCCEED;
233}
234
235str
236CLTsetoptimizer(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
237{
238 int idx;
239 str opt;
240
241 (void) mb;
242 if( pci->argc == 3){
243 idx = *getArgReference_int(stk,pci,1);
244 opt = *getArgReference_str(stk,pci,2);
245 } else {
246 idx = cntxt->idx;
247 opt = *getArgReference_str(stk,pci,1);
248 }
249
250 if( idx < 0 || idx > MAL_MAXCLIENTS)
251 throw(MAL,"clients.setoptimizer","Illegal session id");
252 if (mal_clients[idx].mode == FREECLIENT)
253 throw(MAL,"clients.setoptimizer","Session not active anymore");
254 if (cntxt->user == mal_clients[idx].user || cntxt->user == MAL_ADMIN){
255 if (strcmp(opt, str_nil) == 0)
256 throw(MAL,"clients.setoptimizer","Input string cannot be NULL");
257 if (strlen(opt) >= sizeof(mal_clients[idx].optimizer))
258 throw(MAL,"clients.setoptimizer","Input string is too large");
259 strcpy_len(mal_clients[idx].optimizer, opt,
260 sizeof(mal_clients[idx].optimizer));
261 }
262 return MAL_SUCCEED;
263}
264
265str
266CLTsetworkerlimit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
267{
268 int idx, limit;
269
270 (void) mb;
271 if(pci->argc == 3){
272 idx = *getArgReference_int(stk,pci,1);
273 limit = *getArgReference_int(stk,pci,2);
274 } else {
275 idx = cntxt->idx;
276 limit = *getArgReference_int(stk,pci,1);
277 }
278
279 if( idx < 0 || idx > MAL_MAXCLIENTS)
280 throw(MAL,"clients.setworkerlimit","Illegal session id");
281 if( limit < 0)
282 throw(MAL, "clients.setworkerlimit", "At least one worker needed");
283 if (mal_clients[idx].mode == FREECLIENT)
284 throw(MAL,"clients.setworkerlimit","Session not active anymore");
285 if (cntxt->user == mal_clients[idx].user || cntxt->user == MAL_ADMIN){
286 mal_clients[idx].workerlimit = limit;
287 }
288 return MAL_SUCCEED;
289}
290
291str
292CLTsetmemorylimit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
293{
294 int idx, limit;
295
296 (void) mb;
297 if(pci->argc == 3){
298 idx = *getArgReference_sht(stk,pci,1);
299 limit = *getArgReference_int(stk,pci,2);
300 } else{
301 idx = cntxt->idx;
302 limit = *getArgReference_int(stk,pci,1);
303 }
304
305 if( idx < 0 || idx > MAL_MAXCLIENTS)
306 throw(MAL,"clients.setmemorylimit","Illegal session id");
307 if (mal_clients[idx].mode == FREECLIENT)
308 throw(MAL,"clients.setmemorylimit","Session not active anymore");
309 if (cntxt->user == mal_clients[idx].user || cntxt->user == MAL_ADMIN){
310 mal_clients[idx].memorylimit = limit;
311 }
312 return MAL_SUCCEED;
313}
314
315str
316CLTstopSession(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
317{
318 int idx;
319
320 (void) mb;
321 switch( getArgType(mb,pci,1)){
322 case TYPE_bte:
323 idx = *getArgReference_bte(stk,pci,1);
324 break;
325 case TYPE_sht:
326 idx = *getArgReference_sht(stk,pci,1);
327 break;
328 case TYPE_int:
329 idx = *getArgReference_int(stk,pci,1);
330 break;
331 default:
332 throw(MAL,"clients.stopSession","Unexpected index type");
333 }
334 if( idx < 0 || idx > MAL_MAXCLIENTS)
335 throw(MAL,"clients.stopSession","Illegal session id");
336 if (mal_clients[idx].mode == FREECLIENT)
337 throw(MAL,"clients.stopSession","Session not active anymore");
338 if (cntxt->user == mal_clients[idx].user || cntxt->user == MAL_ADMIN){
339 mal_clients[idx].querytimeout = 1; /* stop client in one microsecond */
340 mal_clients[idx].sessiontimeout = 1; /* stop client session */
341 }
342 /* this forces the designated client to stop at the next instruction */
343 return MAL_SUCCEED;
344}
345
346/* Queries can be temporarily suspended */
347str
348CLTsuspend(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
349{
350 int *id= getArgReference_int(stk,pci,1);
351 (void) cntxt;
352 (void) mb;
353 if ( !(cntxt->user == MAL_ADMIN || mal_clients[*id].user == cntxt->user) )
354 throw(MAL, "client.suspend", INVCRED_ACCESS_DENIED);
355 return MCsuspendClient(*id);
356}
357
358str
359CLTwakeup(void *ret, int *id)
360{
361 (void) ret; /* fool compiler */
362 return MCawakeClient(*id);
363}
364
365/* Set session time out based in seconds. As of December 2019, this function is deprecated */
366str
367CLTsetSessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
368{
369 lng sto;
370 int idx = cntxt->idx;
371
372 (void) mb;
373 if( idx < 0 || idx > MAL_MAXCLIENTS)
374 throw(MAL,"clients.setsession","Illegal session id %d", idx);
375 if (mal_clients[idx].mode == FREECLIENT)
376 throw(MAL,"clients.setsession","Session not active anymore");
377 sto = *getArgReference_lng(stk,pci,1);
378 if (sto < 0)
379 throw(MAL,"clients.setsession","Session timeout should be >= 0");
380 mal_clients[idx].sessiontimeout = sto * 1000000;
381 return MAL_SUCCEED;
382}
383
384/* Set the current query timeout in seconds. As of December 2019, this function is deprecated */
385str
386CLTsetTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
387{
388 lng qto,sto;
389 int idx = cntxt->idx;
390
391 (void) mb;
392 if( idx < 0 || idx > MAL_MAXCLIENTS)
393 throw(MAL,"clients.settimeout","Illegal session id %d", idx);
394 if (mal_clients[idx].mode == FREECLIENT)
395 throw(MAL,"clients.settimeout","Session not active anymore");
396 qto = *getArgReference_lng(stk,pci,1);
397 if (qto < 0)
398 throw(MAL,"clients.settimeout","Query timeout should be >= 0");
399 if (pci->argc == 3) {
400 sto = *getArgReference_lng(stk,pci,2);
401 if( sto < 0)
402 throw(MAL,"clients.settimeout","Session timeout should be >= 0");
403 mal_clients[idx].sessiontimeout = sto * 1000000;
404 }
405 mal_clients[idx].querytimeout = qto * 1000000;
406 return MAL_SUCCEED;
407}
408
409/* set session time out based in seconds, converted into microseconds */
410str
411CLTqueryTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
412{
413 int qto, idx = -1;
414 (void) cntxt;
415 (void) mb;
416 if ( pci->argc == 3){
417 switch( getArgType(mb,pci,1)){
418 case TYPE_bte:
419 idx = *getArgReference_bte(stk,pci,1);
420 break;
421 case TYPE_sht:
422 idx = *getArgReference_sht(stk,pci,1);
423 break;
424 case TYPE_int:
425 idx = *getArgReference_int(stk,pci,1);
426 break;
427 default:
428 throw(MAL,"clients.queryTimeout","Unexpected index type");
429 }
430 qto= *getArgReference_int(stk,pci,2);
431 } else {
432 idx = cntxt->idx;
433 qto= *getArgReference_int(stk,pci,1);
434 }
435 if( qto < 0)
436 throw(MAL,"clients.queryTimeout","Query time-out should be >= 0");
437 mal_clients[idx].querytimeout = (lng) qto * 1000000;
438 return MAL_SUCCEED;
439}
440
441/* Set the current session timeout in seconds */
442str
443CLTsessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
444{
445 int sto = -1, idx = -1;
446
447 (void) cntxt;
448 if( pci->argc == 3){
449 switch( getArgType(mb,pci,1)){
450 case TYPE_bte:
451 idx = *getArgReference_bte(stk,pci,1);
452 break;
453 case TYPE_sht:
454 idx = *getArgReference_sht(stk,pci,1);
455 break;
456 case TYPE_int:
457 idx = *getArgReference_int(stk,pci,1);
458 break;
459 default:
460 throw(MAL,"clients.sessionTimeout","Unexpected index type");
461 }
462 sto = *getArgReference_int(stk,pci,2);
463 } else {
464 idx = cntxt->idx;
465 sto = *getArgReference_int(stk,pci,1);
466 }
467 if( sto < 0)
468 throw(MAL,"clients.sessionTimeout","Session time-out should be >= 0");
469 if( idx < 0 || idx > MAL_MAXCLIENTS)
470 throw(MAL,"clients.sessionTimeout","Illegal session id %d", idx);
471 if (mal_clients[idx].mode == FREECLIENT)
472 throw(MAL,"clients.sessionTimeout","Session not active anymore");
473 mal_clients[idx].sessiontimeout = (lng) sto * 1000000;
474 return MAL_SUCCEED;
475}
476
477/* Retrieve the session time out */
478str
479CLTgetProfile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
480{
481 str *opt= getArgReference_str(stk,pci,0);
482 int *qto= getArgReference_int(stk,pci,1);
483 int *sto= getArgReference_int(stk,pci,2);
484 int *wlim= getArgReference_int(stk,pci,3);
485 int *mlim= getArgReference_int(stk,pci,4);
486 (void) mb;
487 if (!(*opt = GDKstrdup(cntxt->optimizer)))
488 throw(MAL, "clients.getProfile", SQLSTATE(HY001) MAL_MALLOC_FAIL);
489 *qto = (int)(cntxt->querytimeout / 1000000);
490 *sto = (int)(cntxt->sessiontimeout / 1000000);
491 *wlim = cntxt->workerlimit;
492 *mlim = cntxt->memorylimit;
493 return MAL_SUCCEED;
494}
495
496/* Long running queries are traced in the logger
497 * with a message from the interpreter.
498 * This value should be set to minutes to avoid a lengthly log */
499str
500CLTsetPrintTimeout(void *ret, int *secs)
501{
502 (void) ret;
503 if (is_int_nil(*secs))
504 setqptimeout(0);
505 else
506 setqptimeout((lng) *secs * 60 * 1000000);
507 return MAL_SUCCEED;
508}
509
510str CLTmd5sum(str *ret, str *pw) {
511#ifdef HAVE_MD5_UPDATE
512 char *mret = mcrypt_MD5Sum(*pw, strlen(*pw));
513
514 if (!mret)
515 throw(MAL, "clients.md5sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
516 *ret = GDKstrdup(mret);
517 free(mret);
518 if(*ret == NULL)
519 throw(MAL, "clients.md5sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
520 return MAL_SUCCEED;
521#else
522 (void) ret;
523 (void) pw;
524 throw(MAL, "clients.md5sum", SQLSTATE(0A000) PROGRAM_NYI);
525#endif
526}
527
528str CLTsha1sum(str *ret, str *pw) {
529#ifdef HAVE_SHA1_UPDATE
530 char *mret = mcrypt_SHA1Sum(*pw, strlen(*pw));
531
532 if (!mret)
533 throw(MAL, "clients.sha1sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
534 *ret = GDKstrdup(mret);
535 free(mret);
536 if(*ret == NULL)
537 throw(MAL, "clients.sha1sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
538 return MAL_SUCCEED;
539#else
540 (void) ret;
541 (void) pw;
542 throw(MAL, "clients.sha1sum", SQLSTATE(0A000) PROGRAM_NYI);
543#endif
544}
545
546str CLTripemd160sum(str *ret, str *pw) {
547#ifdef HAVE_RIPEMD160_UPDATE
548 char *mret = mcrypt_RIPEMD160Sum(*pw, strlen(*pw));
549
550 if (!mret)
551 throw(MAL, "clients.ripemd160sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
552 *ret = GDKstrdup(mret);
553 free(mret);
554 if(*ret == NULL)
555 throw(MAL, "clients.ripemd160sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
556 return MAL_SUCCEED;
557#else
558 (void) ret;
559 (void) pw;
560 throw(MAL, "clients.ripemd160sum", SQLSTATE(0A000) PROGRAM_NYI);
561#endif
562}
563
564str CLTsha2sum(str *ret, str *pw, int *bits) {
565 char *mret;
566 switch (*bits) {
567#ifdef HAVE_SHA512_UPDATE
568 case 512:
569 mret = mcrypt_SHA512Sum(*pw, strlen(*pw));
570 break;
571#endif
572#ifdef HAVE_SHA384_UPDATE
573 case 384:
574 mret = mcrypt_SHA384Sum(*pw, strlen(*pw));
575 break;
576#endif
577#ifdef HAVE_SHA256_UPDATE
578 case 256:
579 mret = mcrypt_SHA256Sum(*pw, strlen(*pw));
580 break;
581#endif
582#ifdef HAVE_SHA224_UPDATE
583 case 224:
584 mret = mcrypt_SHA224Sum(*pw, strlen(*pw));
585 break;
586#endif
587 default:
588 throw(ILLARG, "clients.sha2sum", "wrong number of bits "
589 "for SHA2 sum: %d", *bits);
590 }
591
592 if (!mret)
593 throw(MAL, "clients.sha2sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
594 *ret = GDKstrdup(mret);
595 free(mret);
596 if(*ret == NULL)
597 throw(MAL, "clients.sha2sum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
598 return MAL_SUCCEED;
599}
600
601str CLTbackendsum(str *ret, str *pw) {
602 char *mret = mcrypt_BackendSum(*pw, strlen(*pw));
603 if (mret == NULL)
604 throw(MAL, "clients.backendsum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
605 *ret = GDKstrdup(mret);
606 free(mret);
607 if(*ret == NULL)
608 throw(MAL, "clients.backendsum", SQLSTATE(HY001) MAL_MALLOC_FAIL);
609 return MAL_SUCCEED;
610}
611
612str CLTaddUser(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
613 oid *ret = getArgReference_oid(stk, pci, 0);
614 str *usr = getArgReference_str(stk, pci, 1);
615 str *pw = getArgReference_str(stk, pci, 2);
616
617 (void)mb;
618
619 return AUTHaddUser(ret, cntxt, *usr, *pw);
620}
621
622str CLTremoveUser(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
623 str *usr;
624 (void)mb;
625
626 usr = getArgReference_str(stk, pci, 1);
627
628 return AUTHremoveUser(cntxt, *usr);
629}
630
631str CLTgetUsername(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
632 str *ret = getArgReference_str(stk, pci, 0);
633 (void)mb;
634
635 return AUTHgetUsername(ret, cntxt);
636}
637
638str CLTgetPasswordHash(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
639 str *ret = getArgReference_str(stk, pci, 0);
640 str *user = getArgReference_str(stk, pci, 1);
641
642 (void)mb;
643
644 return AUTHgetPasswordHash(ret, cntxt, *user);
645}
646
647str CLTchangeUsername(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
648 str *old = getArgReference_str(stk, pci, 1);
649 str *new = getArgReference_str(stk, pci, 2);
650
651 (void)mb;
652
653 return AUTHchangeUsername(cntxt, *old, *new);
654}
655
656str CLTchangePassword(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
657 str *old = getArgReference_str(stk, pci, 1);
658 str *new = getArgReference_str(stk, pci, 2);
659
660 (void)mb;
661
662 return AUTHchangePassword(cntxt, *old, *new);
663}
664
665str CLTsetPassword(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
666 str *usr = getArgReference_str(stk, pci, 1);
667 str *new = getArgReference_str(stk, pci, 2);
668
669 (void)mb;
670
671 return AUTHsetPassword(cntxt, *usr, *new);
672}
673
674str CLTcheckPermission(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
675#ifdef HAVE_SHA1_UPDATE
676 str *usr = getArgReference_str(stk, pci, 1);
677 str *pw = getArgReference_str(stk, pci, 2);
678 str ch = "";
679 str algo = "SHA1";
680 oid id;
681 str pwd,msg;
682
683 (void)mb;
684
685 if (!(pwd = mcrypt_SHA1Sum(*pw, strlen(*pw))))
686 throw(MAL, "clients.checkPermission", SQLSTATE(HY001) MAL_MALLOC_FAIL);
687 msg = AUTHcheckCredentials(&id, cntxt, *usr, pwd, ch, algo);
688 free(pwd);
689 return msg;
690#else
691 (void) cntxt;
692 (void) mb;
693 (void) stk;
694 (void) pci;
695 throw(MAL, "mal.checkPermission", "Required digest algorithm SHA-1 missing");
696#endif
697}
698
699str CLTgetUsers(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
700 bat *ret1 = getArgReference_bat(stk, pci, 0);
701 bat *ret2 = getArgReference_bat(stk, pci, 1);
702 BAT *uid, *nme;
703 str tmp;
704
705 (void)mb;
706
707 tmp = AUTHgetUsers(&uid, &nme, cntxt);
708 if (tmp)
709 return tmp;
710 BBPkeepref(*ret1 = uid->batCacheid);
711 BBPkeepref(*ret2 = nme->batCacheid);
712 return(MAL_SUCCEED);
713}
714
715str
716CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
717 str *ret = getArgReference_str(stk,pci,0);
718 int delay;
719 bit force = FALSE;
720 int leftover;
721 char buf[1024]={"safe to stop last connection"};
722
723 if ( pci->argc == 3)
724 force = *getArgReference_bit(stk,pci,2);
725
726 (void) mb;
727 switch( getArgType(mb,pci,1)){
728 case TYPE_bte:
729 delay = *getArgReference_bte(stk,pci,1);
730 break;
731 case TYPE_sht:
732 delay = *getArgReference_sht(stk,pci,1);
733 break;
734 default:
735 delay = *getArgReference_int(stk,pci,1);
736 break;
737 }
738
739 if (cntxt->user != MAL_ADMIN)
740 throw(MAL,"mal.shutdown", "Administrator rights required");
741 MCstopClients(cntxt);
742 do{
743 if ( (leftover = MCactiveClients()-1) )
744 MT_sleep_ms(1000);
745 delay --;
746 } while (delay > 0 && leftover > 1);
747 if( delay == 0 && leftover > 1)
748 snprintf(buf, 1024,"%d client sessions still running",leftover);
749 *ret = GDKstrdup(buf);
750 if ( force)
751 mal_exit(0);
752 if(*ret == NULL)
753 throw(MAL, "mal.shutdown", SQLSTATE(HY001) MAL_MALLOC_FAIL);
754 return MAL_SUCCEED;
755}
756
757str
758CLTsessions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
759{
760 BAT *id = NULL, *user = NULL, *login = NULL, *sessiontimeout = NULL, *querytimeout = NULL, *idle= NULL;
761 BAT *opt = NULL, *wlimit = NULL, *mlimit = NULL;
762 bat *idId = getArgReference_bat(stk,pci,0);
763 bat *userId = getArgReference_bat(stk,pci,1);
764 bat *loginId = getArgReference_bat(stk,pci,2);
765 bat *idleId = getArgReference_bat(stk,pci,3);
766 bat *optId = getArgReference_bat(stk,pci,4);
767 bat *sessiontimeoutId = getArgReference_bat(stk,pci,5);
768 bat *querytimeoutId = getArgReference_bat(stk,pci,6);
769 bat *wlimitId = getArgReference_bat(stk,pci,7);
770 bat *mlimitId = getArgReference_bat(stk,pci,8);
771 Client c;
772 timestamp ret;
773 int timeout;
774 str msg = NULL;
775
776 (void) cntxt;
777 (void) mb;
778
779 id = COLnew(0, TYPE_int, 0, TRANSIENT);
780 user = COLnew(0, TYPE_str, 0, TRANSIENT);
781 login = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
782 opt = COLnew(0, TYPE_str, 0, TRANSIENT);
783 sessiontimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
784 querytimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
785 wlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
786 mlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
787 idle = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
788
789 if (id == NULL || user == NULL || login == NULL || sessiontimeout == NULL || idle == NULL || querytimeout == NULL ||
790 opt == NULL || wlimit == NULL || mlimit == NULL ){
791 if ( id) BBPunfix(id->batCacheid);
792 if ( user) BBPunfix(user->batCacheid);
793 if ( login) BBPunfix(login->batCacheid);
794 if ( sessiontimeout) BBPunfix(sessiontimeout->batCacheid);
795 if ( querytimeout) BBPunfix(querytimeout->batCacheid);
796 if ( idle) BBPunfix(idle->batCacheid);
797
798 if ( opt) BBPunfix(opt->batCacheid);
799 if ( wlimit) BBPunfix(wlimit->batCacheid);
800 if ( mlimit) BBPunfix(mlimit->batCacheid);
801 throw(SQL,"sql.sessions", SQLSTATE(HY001) MAL_MALLOC_FAIL);
802 }
803
804 MT_lock_set(&mal_contextLock);
805
806 for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) {
807 if (c->mode == RUNCLIENT) {
808 if (BUNappend(user, c->username, false) != GDK_SUCCEED)
809 goto bailout;
810 ret = timestamp_fromtime(c->login);
811 if (is_timestamp_nil(ret)) {
812 msg = createException(SQL, "sql.sessions", SQLSTATE(22003) "Failed to convert user logged time");
813 goto bailout;
814 }
815 if (BUNappend(id, &c->idx, false) != GDK_SUCCEED)
816 goto bailout;
817 if (BUNappend(login, &ret, false) != GDK_SUCCEED)
818 goto bailout;
819 timeout = (int)(c->sessiontimeout / 1000000);
820 if (BUNappend(sessiontimeout, &timeout, false) != GDK_SUCCEED)
821 goto bailout;
822 timeout = (int)(c->querytimeout / 1000000);
823 if (BUNappend(querytimeout, &timeout, false) != GDK_SUCCEED)
824 goto bailout;
825 ret = timestamp_fromtime(c->idle);
826 if (is_timestamp_nil(ret)) {
827 msg = createException(SQL, "sql.sessions", SQLSTATE(22003) "Failed to convert user logged time");
828 goto bailout;
829 }
830 if (BUNappend(idle, &ret, false) != GDK_SUCCEED)
831 goto bailout;
832 if (BUNappend(opt, &c->optimizer, false) != GDK_SUCCEED)
833 goto bailout;
834 if (BUNappend(wlimit, &c->workerlimit, false) != GDK_SUCCEED)
835 goto bailout;
836 if (BUNappend(mlimit, &c->memorylimit, false) != GDK_SUCCEED)
837 goto bailout;
838 }
839 }
840 MT_lock_unset(&mal_contextLock);
841 BBPkeepref(*idId = id->batCacheid);
842 BBPkeepref(*userId = user->batCacheid);
843 BBPkeepref(*loginId = login->batCacheid);
844 BBPkeepref(*sessiontimeoutId = sessiontimeout->batCacheid);
845 BBPkeepref(*querytimeoutId = querytimeout->batCacheid);
846 BBPkeepref(*idleId = idle->batCacheid);
847
848 BBPkeepref(*optId = opt->batCacheid);
849 BBPkeepref(*wlimitId = wlimit->batCacheid);
850 BBPkeepref(*mlimitId = mlimit->batCacheid);
851 return MAL_SUCCEED;
852
853bailout:
854 MT_lock_unset(&mal_contextLock);
855 BBPunfix(id->batCacheid);
856 BBPunfix(user->batCacheid);
857 BBPunfix(login->batCacheid);
858 BBPunfix(sessiontimeout->batCacheid);
859 BBPunfix(querytimeout->batCacheid);
860 BBPunfix(idle->batCacheid);
861
862 BBPunfix(opt->batCacheid);
863 BBPunfix(wlimit->batCacheid);
864 BBPunfix(mlimit->batCacheid);
865 return msg;
866}
867