35
35
#define HTTP_CONTENT_TYPE_JSON "Content-Type: " HTTP_APP_JSON \
36
36
"; charset=utf-8"
37
37
38
+ /* HTTP header API Key authentication-specific */
39
+ #define HTTP_AUTH_API_KEY "Authorization: ApiKey "
40
+ #define APIKEY_BUFF_SIZE 512
41
+
38
42
/* Elasticsearch/SQL data types */
39
43
/* 2 */
40
44
#define TYPE_IP "IP"
@@ -382,6 +386,10 @@ static void cleanup_curl(esodbc_dbc_st *dbc)
382
386
return ;
383
387
}
384
388
DBGH (dbc , "libcurl: handle 0x%p cleanup." , dbc -> curl );
389
+ if (dbc -> curl_hdrs ) {
390
+ curl_slist_free_all (dbc -> curl_hdrs );
391
+ dbc -> curl_hdrs = NULL ;
392
+ }
385
393
dbc -> curl_err = CURLE_OK ;
386
394
dbc -> curl_err_buff [0 ] = '\0' ;
387
395
@@ -442,11 +450,34 @@ SQLRETURN dbc_curl_set_url(esodbc_dbc_st *dbc, int url_type)
442
450
return SQL_ERROR ;
443
451
}
444
452
453
+ /* copy of unexported Curl_slist_duplicate() libcurl function */
454
+ static struct curl_slist * curl_slist_duplicate (struct curl_slist * inlist )
455
+ {
456
+ struct curl_slist * outlist = NULL ;
457
+ struct curl_slist * tmp ;
458
+
459
+ while (inlist ) {
460
+ tmp = curl_slist_append (outlist , inlist -> data );
461
+
462
+ if (!tmp ) {
463
+ curl_slist_free_all (outlist );
464
+ return NULL ;
465
+ }
466
+
467
+ outlist = tmp ;
468
+ inlist = inlist -> next ;
469
+ }
470
+ return outlist ;
471
+ }
472
+
445
473
static SQLRETURN dbc_curl_init (esodbc_dbc_st * dbc )
446
474
{
447
475
CURL * curl ;
448
476
SQLRETURN ret ;
449
477
BOOL compress ;
478
+ char apikey_buff [APIKEY_BUFF_SIZE ], * apikey_ptr = NULL ;
479
+ struct curl_slist * curl_hdrs ;
480
+
450
481
451
482
assert (! dbc -> curl );
452
483
@@ -467,14 +498,6 @@ static SQLRETURN dbc_curl_init(esodbc_dbc_st *dbc)
467
498
goto err ;
468
499
}
469
500
470
- /* set the HTTP headers: Content-Type, Accept */
471
- dbc -> curl_err = curl_easy_setopt (curl , CURLOPT_HTTPHEADER ,
472
- dbc -> pack_json ? json_headers : cbor_headers );
473
- if (dbc -> curl_err != CURLE_OK ) {
474
- ERRH (dbc , "libcurl: failed to set HTTP headers list." );
475
- goto err ;
476
- }
477
-
478
501
/* set the behavior for redirection */
479
502
dbc -> curl_err = curl_easy_setopt (curl , CURLOPT_FOLLOWLOCATION ,
480
503
dbc -> follow );
@@ -582,8 +605,55 @@ static SQLRETURN dbc_curl_init(esodbc_dbc_st *dbc)
582
605
goto err ;
583
606
}
584
607
}
608
+ } else if (dbc -> api_key .cnt ) {
609
+ if (sizeof (HTTP_AUTH_API_KEY ) + dbc -> api_key .cnt <
610
+ sizeof (apikey_buff )) {
611
+ apikey_ptr = apikey_buff ;
612
+ } else {
613
+ DBGH (dbc , "static buffer size %zuB less than required %zuB, "
614
+ "allocating." , sizeof (apikey_buff ), sizeof (HTTP_AUTH_API_KEY ) +
615
+ dbc -> api_key .cnt );
616
+ apikey_ptr = malloc (sizeof (HTTP_AUTH_API_KEY ) + dbc -> api_key .cnt );
617
+ if (! apikey_ptr ) {
618
+ ERRNH (dbc , "OOM for %zuB." , sizeof (HTTP_AUTH_API_KEY ) +
619
+ dbc -> api_key .cnt );
620
+ goto err ;
621
+ }
622
+ }
623
+ memcpy (apikey_ptr , HTTP_AUTH_API_KEY , sizeof (HTTP_AUTH_API_KEY ) - 1 );
624
+ memcpy (apikey_ptr + sizeof (HTTP_AUTH_API_KEY ) - 1 , dbc -> api_key .str ,
625
+ dbc -> api_key .cnt );
626
+ apikey_ptr [sizeof (HTTP_AUTH_API_KEY ) - 1 + dbc -> api_key .cnt ] = '\0' ;
627
+
628
+ dbc -> curl_hdrs = curl_slist_append (NULL , apikey_ptr );
629
+ if (apikey_ptr != apikey_buff ) {
630
+ free (apikey_ptr );
631
+ apikey_ptr = NULL ;
632
+ }
633
+ if (! dbc -> curl_hdrs ) {
634
+ ERRH (dbc , "libcurl: failed to init API key Auth header." );
635
+ goto err ;
636
+ }
585
637
} else {
586
- INFOH (dbc , "no username provided: auth disabled." );
638
+ INFOH (dbc , "no username or API key provided: auth disabled." );
639
+ }
640
+
641
+ /* set the HTTP headers: Content-Type, Accept, Authorization(?) */
642
+ curl_hdrs = dbc -> pack_json ? json_headers : cbor_headers ;
643
+ /* is there already an Autorization header set? then chain the pack hdrs */
644
+ if (dbc -> curl_hdrs ) {
645
+ if (! (curl_hdrs = curl_slist_duplicate (curl_hdrs ))) {
646
+ ERRNH (dbc , "failed duplicating packing format headers." );
647
+ goto err ;
648
+ }
649
+ dbc -> curl_hdrs -> next = curl_hdrs ;
650
+ /* if there's no Authz header, the pack headers won't be dup'd */
651
+ curl_hdrs = dbc -> curl_hdrs ;
652
+ }
653
+ dbc -> curl_err = curl_easy_setopt (curl , CURLOPT_HTTPHEADER , curl_hdrs );
654
+ if (dbc -> curl_err != CURLE_OK ) {
655
+ ERRH (dbc , "libcurl: failed to set HTTP headers list." );
656
+ goto err ;
587
657
}
588
658
589
659
/* proxy parameters */
@@ -1322,6 +1392,14 @@ SQLRETURN config_dbc(esodbc_dbc_st *dbc, esodbc_dsn_attrs_st *attrs)
1322
1392
/* indicates the presence of a non-empty password */
1323
1393
INFOH (dbc , "connection PWD: " ESODBC_PWD_VAL_SUBST "." );
1324
1394
}
1395
+ } else if (attrs -> api_key .cnt ) {
1396
+ if (! wstr_to_utf8 (& attrs -> api_key , & dbc -> api_key )) {
1397
+ ERRH (dbc , "failed to convert API key [%zu] `" LWPDL "` to UTF8." ,
1398
+ attrs -> api_key .cnt , LWSTR (& attrs -> api_key ));
1399
+ SET_HDIAG (dbc , SQL_STATE_HY000 , "API key UTF8 conversion failed" ,
1400
+ 0 );
1401
+ goto err ;
1402
+ }
1325
1403
}
1326
1404
1327
1405
/* "follow location" param for liburl */
0 commit comments