mirror of
https://github.com/curl/curl.git
synced 2026-08-24 11:33:33 +03:00
OS400: new SSL backend GSKit
This commit is contained in:
parent
464c8693d2
commit
0eba02fd41
15 changed files with 1530 additions and 30 deletions
|
|
@ -39,22 +39,24 @@ header files are thus altered during build process to use this pragma, in
|
|||
order to force libcurl enums of being type int (the pragma disposition in use
|
||||
before inclusion is restored before resuming the including unit compilation).
|
||||
|
||||
Three SSL implementations were present in libcurl. Nevertheless, none of them
|
||||
is available on OS/400. To support SSL on OS/400, a fourth implementation has
|
||||
been added (qssl.[ch]). There is no way to have different certificate stores
|
||||
for CAs and for personal/application certificates/key. More, the SSL context
|
||||
may be defined as an application identifier in the main certificate store,
|
||||
or as a keyring file. As a consequence, the meaning of some fields have been
|
||||
slightly altered:
|
||||
_ The "certificate identifier" is taken from CURLOPT_SSLCERT if defined, else
|
||||
from CURLOPT_CAINFO.
|
||||
_ The certificate identifier is then used as an application identifier in the
|
||||
main certificate store. If successful, this context is used.
|
||||
_ If the previous step failed, the certificate identifier is used as the file
|
||||
name of a keyring. CURLOPT_KEYPASSWD is used here as the keyring password.
|
||||
_ The default ca-bundle (CURLOPT_CAINFO) is set to the main certificate store's
|
||||
keyring file name: this allows to use the system global CAs by default. (In that
|
||||
case, the keyring password is safely recovered from the system... IBM dixit!)
|
||||
Two SSL implementations are available to libcurl on OS/400: QsoSSL which is
|
||||
obsolescent, does not support asynchronous I/O and only allows a single SSL
|
||||
context within a job, and GSKit that does not suffer from these limitations
|
||||
and is able to provide some information about the server certificate.
|
||||
Both implementations of SSL are working on "certificate stores" or keyrings,
|
||||
rather than individual certificate/key files. Certificate stores, as weel as
|
||||
"certificate labels" are managed by external IBM-defined applications.
|
||||
There are two ways to specify an SSL context:
|
||||
- By an application identifier.
|
||||
- By a keyring file pathname and (optionally) certificate label.
|
||||
To identify an SSL context by application identifier, use option
|
||||
SETOPT_SSLCERT to specify the application identifier.
|
||||
To address an SSL context by keyring and certificate label, use CURLOPT_CAINFO
|
||||
to set-up the keyring pathname, CURLOPT_SSLCERT to define the certificate label
|
||||
(omitting it will cause the default certificate in keyring to be used) and
|
||||
CURLOPT_KEYPASSWD to give the keyring password. If SSL is used without
|
||||
defining any of these options, the default (i.e.: system) keyring is used for
|
||||
server certificate validation.
|
||||
|
||||
Non-standard EBCDIC wrapper prototypes are defined in an additional header
|
||||
file: ccsidcurl.h. These should be self-explanatory to an OS/400-aware
|
||||
|
|
@ -154,6 +156,14 @@ use:
|
|||
CURLINFO_PRIMARY_IP
|
||||
CURLINFO_RTSP_SESSION_ID
|
||||
CURLINFO_LOCAL_IP
|
||||
Likewise, the following options are followed by a struct curl_slist * * and a
|
||||
CCSID.
|
||||
CURLINFO_SSL_ENGINES
|
||||
CURLINFO_COOKIELIST
|
||||
Lists returned should be released with curl_slist_free_all() after use.
|
||||
Option CURLINFO_CERTINFO is followed by a struct curl_certinfo * * and a
|
||||
CCSID. Returned structures sould be free'ed using curl_certinfo_free_all() after
|
||||
use.
|
||||
Other options are processed like in curl_easy_getinfo().
|
||||
|
||||
Standard compilation environment does support neither autotools nor make;
|
||||
|
|
@ -200,6 +210,8 @@ _ As a prerequisite, QADRT development environment must be installed.
|
|||
_ Install the curl source directory in IFS.
|
||||
_ Enter shell (QSH)
|
||||
_ Change current directory to the curl installation directory
|
||||
- If the SSL backend has to be changed, edit file lib/config-os400.h
|
||||
accordingly.
|
||||
_ Change current directory to ./packages/OS400
|
||||
_ Edit file iniscript.sh. You may want to change tunable configuration
|
||||
parameters, like debug info generation, optimisation level, listing option,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
|
@ -42,6 +42,11 @@
|
|||
#include <qsossl.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
#include <gskssl.h>
|
||||
#include <qsoasync.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
#include <gssapi.h>
|
||||
#endif
|
||||
|
|
@ -451,6 +456,412 @@ Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp)
|
|||
#endif /* USE_QSOSSL */
|
||||
|
||||
|
||||
#ifdef USE_GSKIT
|
||||
|
||||
/* ASCII wrappers for the GSKit procedures. */
|
||||
|
||||
/*
|
||||
* EBCDIC --> ASCII string mapping table.
|
||||
* Some strings returned by GSKit are dynamically allocated and automatically
|
||||
* released when closing the handle.
|
||||
* To provide the same functionality, we use a "private" handle that
|
||||
* holds the GSKit handle and a list of string mappings. This will allow
|
||||
* avoid conversion of already converted strings and releasing them upon
|
||||
* close time.
|
||||
*/
|
||||
|
||||
struct gskstrlist {
|
||||
struct gskstrlist * next;
|
||||
const char * ebcdicstr;
|
||||
const char * asciistr;
|
||||
};
|
||||
|
||||
struct Curl_gsk_descriptor {
|
||||
gsk_handle h;
|
||||
struct gskstrlist * strlist;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_environment_open(gsk_handle * my_env_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
gsk_handle h;
|
||||
int rc;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(!(p = (struct Curl_gsk_descriptor *) malloc(sizeof *p)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
p->strlist = (struct gskstrlist *) NULL;
|
||||
if((rc = gsk_environment_open(&p->h)) != GSK_OK)
|
||||
free(p);
|
||||
else
|
||||
*my_env_handle = (gsk_handle) p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
|
||||
gsk_handle * my_session_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
gsk_handle h;
|
||||
int rc;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
if(!my_session_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
|
||||
if(!(p = (struct Curl_gsk_descriptor *) malloc(sizeof *p)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
p->strlist = (struct gskstrlist *) NULL;
|
||||
if((rc = gsk_secure_soc_open(h, &p->h)) != GSK_OK)
|
||||
free(p);
|
||||
else
|
||||
*my_session_handle = (gsk_handle) p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gsk_free_handle(struct Curl_gsk_descriptor * p)
|
||||
|
||||
{
|
||||
struct gskstrlist * q;
|
||||
|
||||
while ((q = p->strlist)) {
|
||||
p->strlist = q;
|
||||
free((void *) q->asciistr);
|
||||
free(q);
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_environment_close(gsk_handle * my_env_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
int rc;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(!*my_env_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) *my_env_handle;
|
||||
if ((rc = gsk_environment_close(&p->h)) == GSK_OK) {
|
||||
gsk_free_handle(p);
|
||||
*my_env_handle = (gsk_handle) NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
int rc;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(!*my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) *my_session_handle;
|
||||
if ((rc = gsk_secure_soc_close(&p->h)) == GSK_OK) {
|
||||
gsk_free_handle(p);
|
||||
*my_session_handle = (gsk_handle) NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_environment_init(gsk_handle my_env_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_env_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_env_handle;
|
||||
return gsk_environment_init(p->h);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_init(gsk_handle my_session_handle)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_init(p->h);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
|
||||
const char * buffer, int bufSize)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
char * ebcdicbuf;
|
||||
int rc;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
if(!buffer)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
if(bufSize < 0)
|
||||
return GSK_ATTRIBUTE_INVALID_LENGTH;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
if(!bufSize)
|
||||
bufSize = strlen(buffer);
|
||||
if (!(ebcdicbuf = malloc(bufSize + 1)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
|
||||
ebcdicbuf[bufSize] = '\0';
|
||||
rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize);
|
||||
free(ebcdicbuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE enumValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_set_enum(p->h, enumID, enumValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID, int numValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_set_numeric_value(p->h, numID, numValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
|
||||
GSK_CALLBACK_ID callBackID,
|
||||
void * callBackAreaPtr)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cachestring(struct Curl_gsk_descriptor * p,
|
||||
const char * ebcdicbuf, int bufsize, const char * * buffer)
|
||||
|
||||
{
|
||||
int rc;
|
||||
char * asciibuf;
|
||||
struct gskstrlist * sp;
|
||||
|
||||
for (sp = p->strlist; sp; sp = sp->next)
|
||||
if(sp->ebcdicstr == ebcdicbuf)
|
||||
break;
|
||||
if(!sp) {
|
||||
if(!(sp = (struct gskstrlist *) malloc(sizeof *sp)))
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
if(!(asciibuf = malloc(bufsize + 1))) {
|
||||
free(sp);
|
||||
return GSK_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize);
|
||||
asciibuf[bufsize] = '\0';
|
||||
sp->ebcdicstr = ebcdicbuf;
|
||||
sp->asciistr = asciibuf;
|
||||
sp->next = p->strlist;
|
||||
p->strlist = sp;
|
||||
}
|
||||
*buffer = sp->asciistr;
|
||||
return GSK_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
|
||||
const char * * buffer, int * bufSize)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
int rc;
|
||||
const char * mybuf;
|
||||
int mylen;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
if(!buffer || !bufSize)
|
||||
return GSK_OS400_ERROR_INVALID_POINTER;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
if ((rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen)) != GSK_OK)
|
||||
return rc;
|
||||
if((rc = cachestring(p, mybuf, mylen, buffer)) == GSK_OK)
|
||||
*bufSize = mylen;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE * enumValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_get_enum(p->h, enumID, enumValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID, int * numValue)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
return gsk_attribute_get_numeric_value(p->h, numID, numValue);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
|
||||
GSK_CERT_ID certID,
|
||||
const gsk_cert_data_elem * * certDataElem,
|
||||
int * certDataElementCount)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_gsk_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_gsk_handle;
|
||||
/* No need to convert code: text results are already in ASCII. */
|
||||
return gsk_attribute_get_cert_info(p->h, certID,
|
||||
certDataElem, certDataElementCount);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_misc(p->h, miscID);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer,
|
||||
int readBufSize, int * amtRead)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer,
|
||||
int writeBufSize, int * amtWritten)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
Curl_gsk_strerror_a(int gsk_return_value)
|
||||
|
||||
{
|
||||
int i;
|
||||
const char * cp;
|
||||
char * cp2;
|
||||
|
||||
cp = gsk_strerror(gsk_return_value);
|
||||
|
||||
if (!cp)
|
||||
return cp;
|
||||
|
||||
i = strlen(cp);
|
||||
|
||||
if (!(cp2 = Curl_thread_buffer(LK_GSK_ERROR, MAX_CONV_EXPANSION * i + 1)))
|
||||
return cp2;
|
||||
|
||||
i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
|
||||
cp2[i] = '\0';
|
||||
return cp2;
|
||||
}
|
||||
|
||||
int
|
||||
Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
|
||||
int IOCompletionPort,
|
||||
Qso_OverlappedIO_t * communicationsArea)
|
||||
|
||||
{
|
||||
struct Curl_gsk_descriptor * p;
|
||||
|
||||
if(!my_session_handle)
|
||||
return GSK_INVALID_HANDLE;
|
||||
p = (struct Curl_gsk_descriptor *) my_session_handle;
|
||||
return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea);
|
||||
}
|
||||
|
||||
#endif /* USE_GSKIT */
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
|
||||
/* ASCII wrappers for the GSSAPI procedures. */
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
typedef enum {
|
||||
LK_SSL_ERROR,
|
||||
LK_GSK_ERROR,
|
||||
LK_LDAP_ERROR,
|
||||
LK_CURL_VERSION,
|
||||
LK_VERSION_INFO,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue